From 848ad99dbe33c52e73ecdd9af601de7fdf355ab6 Mon Sep 17 00:00:00 2001 From: Hung-Wei Hung Date: Sun, 25 Aug 2019 21:34:10 +0800 Subject: [PATCH 001/435] Fix #79428 --- .../contrib/snippet/snippetVariables.ts | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index a1c080d2b45..cad1c3ad589 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -262,7 +262,7 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { } resolve(variable: Variable): string | undefined { - if (variable.name !== 'WORKSPACE_NAME' || !this._workspaceService) { + if ((variable.name !== 'WORKSPACE_NAME' && variable.name !== 'WORKSPACE_FOLDER') || !this._workspaceService) { return undefined; } @@ -272,13 +272,31 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { } if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) { - return path.basename(workspaceIdentifier.path); + if (variable.name === 'WORKSPACE_NAME') { + return path.basename(workspaceIdentifier.path); + } + if (variable.name === 'WORKSPACE_FOLDER') { + return workspaceIdentifier.fsPath; + } + return undefined; } let filename = path.basename(workspaceIdentifier.configPath.path); + if (variable.name === 'WORKSPACE_FOLDER') { + let folderpath = workspaceIdentifier.configPath.fsPath; + if (endsWith(folderpath, filename)) { + folderpath = folderpath.substr(0, folderpath.length - filename.length - 1); + } + return folderpath; + } + if (endsWith(filename, WORKSPACE_EXTENSION)) { filename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1); } - return filename; + if (variable.name === 'WORKSPACE_NAME') { + return filename; + } + + return undefined; } } From ca5c274ad978cadeae3f391ed57e2a7d4697eee6 Mon Sep 17 00:00:00 2001 From: Hung-Wei Hung Date: Thu, 29 Aug 2019 01:04:16 +0800 Subject: [PATCH 002/435] Fix #79428 - normalize drive letter --- src/vs/editor/contrib/snippet/snippetVariables.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index cad1c3ad589..97f854fdbab 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -14,6 +14,7 @@ import { getLeadingWhitespace, commonPrefixLength, isFalsyOrWhitespace, pad, end import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { isSingleFolderWorkspaceIdentifier, toWorkspaceIdentifier, WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; import { ILabelService } from 'vs/platform/label/common/label'; +import { normalizeDriveLetter } from 'vs/base/common/labels'; export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze({ 'CURRENT_YEAR': true, @@ -43,6 +44,7 @@ export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze( 'BLOCK_COMMENT_END': true, 'LINE_COMMENT': true, 'WORKSPACE_NAME': true, + 'WORKSPACE_FOLDER': true, }); export class CompositeSnippetVariableResolver implements VariableResolver { @@ -276,7 +278,7 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { return path.basename(workspaceIdentifier.path); } if (variable.name === 'WORKSPACE_FOLDER') { - return workspaceIdentifier.fsPath; + return normalizeDriveLetter(workspaceIdentifier.fsPath); } return undefined; } @@ -287,7 +289,7 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { if (endsWith(folderpath, filename)) { folderpath = folderpath.substr(0, folderpath.length - filename.length - 1); } - return folderpath; + return (folderpath ? normalizeDriveLetter(folderpath) : '/'); } if (endsWith(filename, WORKSPACE_EXTENSION)) { From 631eee426a7bc7cd1cf0a709e196e5e6df3c643b Mon Sep 17 00:00:00 2001 From: Hung-Wei Hung Date: Thu, 29 Aug 2019 01:04:34 +0800 Subject: [PATCH 003/435] Fix #79428 - add tests --- .../editor/contrib/snippet/test/snippetVariables.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts index b4412f1d130..3e9b755a499 100644 --- a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts @@ -294,7 +294,7 @@ suite('Snippet Variables Resolver', function () { assert.equal(snippet.toString(), 'It is not line 10'); }); - test('Add workspace name variable for snippets #68261', function () { + test('Add workspace name and folder variables for snippets #68261', function () { let workspace: IWorkspace; let resolver: VariableResolver; @@ -317,14 +317,21 @@ suite('Snippet Variables Resolver', function () { // empty workspace workspace = new Workspace(''); assertVariableResolve(resolver, 'WORKSPACE_NAME', undefined); + assertVariableResolve(resolver, 'WORKSPACE_FOLDER', undefined); // single folder workspace without config workspace = new Workspace('', [toWorkspaceFolder(URI.file('/folderName'))]); assertVariableResolve(resolver, 'WORKSPACE_NAME', 'folderName'); + if (!isWindows) { + assertVariableResolve(resolver, 'WORKSPACE_FOLDER', '/folderName'); + } // workspace with config const workspaceConfigPath = URI.file('testWorkspace.code-workspace'); workspace = new Workspace('', toWorkspaceFolders([{ path: 'folderName' }], workspaceConfigPath), workspaceConfigPath); assertVariableResolve(resolver, 'WORKSPACE_NAME', 'testWorkspace'); + if (!isWindows) { + assertVariableResolve(resolver, 'WORKSPACE_FOLDER', '/'); + } }); }); From 4b90d9ba82a3b7340139990dde9db87874a0ac44 Mon Sep 17 00:00:00 2001 From: al Date: Thu, 5 Sep 2019 00:03:16 +0300 Subject: [PATCH 004/435] Add branch name to commit input box --- extensions/git/src/commands.ts | 3 ++- extensions/git/src/repository.ts | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index dfc7bb75fb9..ffd729d002e 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1370,9 +1370,10 @@ export class CommandCenter { value = (await repository.getCommit(repository.HEAD.commit)).message; } + const branchName = repository.getBranchName(); return await window.showInputBox({ value, - placeHolder: localize('commit message', "Commit message"), + placeHolder: branchName ? localize('commitMessageWithHeadLabel2', "Message (commit on '{0}')", branchName) : localize('commit message', "Commit message"), prompt: localize('provide commit message', "Please provide a commit message"), ignoreFocusOut: true }); diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 1b9f7fbd89a..c2cb0a8a25b 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1653,20 +1653,26 @@ export class Repository implements Disposable { } private updateInputBoxPlaceholder(): void { - const HEAD = this.HEAD; - - if (HEAD) { - const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; - const tagName = tag && tag.name; - const head = HEAD.name || tagName || (HEAD.commit || '').substr(0, 8); + const branchName = this.getBranchName(); + if (branchName) { // '{0}' will be replaced by the corresponding key-command later in the process, which is why it needs to stay. - this._sourceControl.inputBox.placeholder = localize('commitMessageWithHeadLabel', "Message ({0} to commit on '{1}')", "{0}", head); + this._sourceControl.inputBox.placeholder = localize('commitMessageWithHeadLabel', "Message ({0} to commit on '{1}')", "{0}", branchName); } else { this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message ({0} to commit)"); } } + getBranchName(): string | undefined { + const HEAD = this.HEAD; + if (HEAD === undefined) { + return; + } + const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; + const tagName = tag && tag.name; + return HEAD.name || tagName || (HEAD.commit || '').substr(0, 8); + } + dispose(): void { this.disposables = dispose(this.disposables); } From 4afe989cfad04b5f6eb961188a874d7c3e21f27b Mon Sep 17 00:00:00 2001 From: al Date: Sun, 8 Sep 2019 22:40:11 +0300 Subject: [PATCH 005/435] =?UTF-8?q?=F0=9F=92=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/git/src/commands.ts | 12 +++++++++--- extensions/git/src/repository.ts | 25 ++++++++++++++----------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index ffd729d002e..cc6cbbaf16c 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -5,7 +5,7 @@ import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, MessageOptions, WorkspaceFolder } from 'vscode'; import { Git, CommitOptions, Stash, ForcePushMode } from './git'; -import { Repository, Resource, ResourceGroupType } from './repository'; +import { Repository, Resource, ResourceGroupType, getBranchName } from './repository'; import { Model } from './model'; import { toGitUri, fromGitUri } from './uri'; import { grep, isDescendant, pathEquals } from './util'; @@ -1370,10 +1370,16 @@ export class CommandCenter { value = (await repository.getCommit(repository.HEAD.commit)).message; } - const branchName = repository.getBranchName(); + let placeHolder; + const branchName = getBranchName(repository.HEAD, repository.refs); + if (branchName) { + placeHolder = localize('commitMessageWithHeadLabel2', "Message (commit on '{0}')", branchName); + } else { + placeHolder = localize('commit message', "Commit message"); + } return await window.showInputBox({ value, - placeHolder: branchName ? localize('commitMessageWithHeadLabel2', "Message (commit on '{0}')", branchName) : localize('commit message', "Commit message"), + placeHolder, prompt: localize('provide commit message', "Please provide a commit message"), ignoreFocusOut: true }); diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index c2cb0a8a25b..781717c04d6 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1653,7 +1653,7 @@ export class Repository implements Disposable { } private updateInputBoxPlaceholder(): void { - const branchName = this.getBranchName(); + const branchName = getBranchName(this.HEAD, this.refs); if (branchName) { // '{0}' will be replaced by the corresponding key-command later in the process, which is why it needs to stay. @@ -1663,17 +1663,20 @@ export class Repository implements Disposable { } } - getBranchName(): string | undefined { - const HEAD = this.HEAD; - if (HEAD === undefined) { - return; - } - const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; - const tagName = tag && tag.name; - return HEAD.name || tagName || (HEAD.commit || '').substr(0, 8); - } - dispose(): void { this.disposables = dispose(this.disposables); } } + +export function getBranchName(HEAD: Repository['HEAD'], refs: Repository['refs']): string | undefined { + if (!HEAD) { + return; + } + const tag = refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; + const tagName = tag && tag.name; + const branchName = HEAD.name || tagName || HEAD.commit; + if (!branchName) { + return; + } + return branchName.substr(0, 8); +} From 6ec5f47c0bfb8adb5b0676c76ff3f76725995a47 Mon Sep 17 00:00:00 2001 From: al Date: Mon, 9 Sep 2019 21:40:13 +0300 Subject: [PATCH 006/435] Just compare to undefined --- extensions/git/src/repository.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 781717c04d6..9882b79ff12 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1669,13 +1669,13 @@ export class Repository implements Disposable { } export function getBranchName(HEAD: Repository['HEAD'], refs: Repository['refs']): string | undefined { - if (!HEAD) { + if (HEAD === undefined) { return; } const tag = refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; const tagName = tag && tag.name; const branchName = HEAD.name || tagName || HEAD.commit; - if (!branchName) { + if (branchName === undefined) { return; } return branchName.substr(0, 8); From 33a1ad1be8c557f3221abc1ac9940132edabfc90 Mon Sep 17 00:00:00 2001 From: Hung-Wei Hung Date: Wed, 11 Sep 2019 23:30:17 +0800 Subject: [PATCH 007/435] Fix #79428 - refactor workspace variable resolver --- .../contrib/snippet/snippetVariables.ts | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index 97f854fdbab..450a6c2e65a 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -12,9 +12,10 @@ import { VariableResolver, Variable, Text } from 'vs/editor/contrib/snippet/snip import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { getLeadingWhitespace, commonPrefixLength, isFalsyOrWhitespace, pad, endsWith } from 'vs/base/common/strings'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { isSingleFolderWorkspaceIdentifier, toWorkspaceIdentifier, WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; +import { isSingleFolderWorkspaceIdentifier, toWorkspaceIdentifier, WORKSPACE_EXTENSION, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { ILabelService } from 'vs/platform/label/common/label'; import { normalizeDriveLetter } from 'vs/base/common/labels'; +import { URI } from 'vs/base/common/uri'; export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze({ 'CURRENT_YEAR': true, @@ -264,7 +265,7 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { } resolve(variable: Variable): string | undefined { - if ((variable.name !== 'WORKSPACE_NAME' && variable.name !== 'WORKSPACE_FOLDER') || !this._workspaceService) { + if (!this._workspaceService) { return undefined; } @@ -273,32 +274,35 @@ export class WorkspaceBasedVariableResolver implements VariableResolver { return undefined; } - if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) { - if (variable.name === 'WORKSPACE_NAME') { - return path.basename(workspaceIdentifier.path); - } - if (variable.name === 'WORKSPACE_FOLDER') { - return normalizeDriveLetter(workspaceIdentifier.fsPath); - } - return undefined; - } - - let filename = path.basename(workspaceIdentifier.configPath.path); - if (variable.name === 'WORKSPACE_FOLDER') { - let folderpath = workspaceIdentifier.configPath.fsPath; - if (endsWith(folderpath, filename)) { - folderpath = folderpath.substr(0, folderpath.length - filename.length - 1); - } - return (folderpath ? normalizeDriveLetter(folderpath) : '/'); - } - - if (endsWith(filename, WORKSPACE_EXTENSION)) { - filename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1); - } if (variable.name === 'WORKSPACE_NAME') { - return filename; + return this._resolveWorkspaceName(workspaceIdentifier); + } else if (variable.name === 'WORKSPACE_FOLDER') { + return this._resoveWorkspacePath(workspaceIdentifier); } return undefined; } + private _resolveWorkspaceName(workspaceIdentifier: IWorkspaceIdentifier | URI): string | undefined { + if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) { + return path.basename(workspaceIdentifier.path); + } + + let filename = path.basename(workspaceIdentifier.configPath.path); + if (endsWith(filename, WORKSPACE_EXTENSION)) { + filename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1); + } + return filename; + } + private _resoveWorkspacePath(workspaceIdentifier: IWorkspaceIdentifier | URI): string | undefined { + if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) { + return normalizeDriveLetter(workspaceIdentifier.fsPath); + } + + let filename = path.basename(workspaceIdentifier.configPath.path); + let folderpath = workspaceIdentifier.configPath.fsPath; + if (endsWith(folderpath, filename)) { + folderpath = folderpath.substr(0, folderpath.length - filename.length - 1); + } + return (folderpath ? normalizeDriveLetter(folderpath) : '/'); + } } From fd16fee02abe869fa4cc10e8bcab41b8fe160aea Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Sun, 22 Sep 2019 21:05:11 -0500 Subject: [PATCH 008/435] Fix #80394 --- .../editor/contrib/snippet/snippetParser.ts | 28 ++++++++----------- .../snippet/test/snippetParser.test.ts | 13 +++++++++ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetParser.ts b/src/vs/editor/contrib/snippet/snippetParser.ts index 61e0fd2a802..5e666885a67 100644 --- a/src/vs/editor/contrib/snippet/snippetParser.ts +++ b/src/vs/editor/contrib/snippet/snippetParser.ts @@ -664,27 +664,23 @@ export class SnippetParser { } private _until(type: TokenType): false | string { - if (this._token.type === TokenType.EOF) { - return false; - } - let res = ''; - let pos = this._token.pos; - let prevToken = { type: TokenType.EOF, pos: 0, len: 0 }; - - while (this._token.type !== type || prevToken.type === TokenType.Backslash) { - if (this._token.type === type) { - res += this._scanner.value.substring(pos, prevToken.pos); - pos = this._token.pos; - } - prevToken = this._token; - this._token = this._scanner.next(); + let start = this._token; + while (this._token.type !== type) { if (this._token.type === TokenType.EOF) { return false; + } else if (this._token.type === TokenType.Backslash) { + const nextToken = this._scanner.next(); + if (nextToken.type !== TokenType.Dollar + && nextToken.type !== TokenType.CurlyClose + && nextToken.type !== TokenType.Backslash) { + return false; + } } + this._token = this._scanner.next(); } - res += this._scanner.value.substring(pos, this._token.pos); + let value = this._scanner.value.substring(start.pos, this._token.pos).replace(/\\(\$|}|\\)/g, '$1'); this._token = this._scanner.next(); - return res; + return value; } private _parse(marker: Marker): boolean { diff --git a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts index f999da850bc..ba019cdc3cb 100644 --- a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts @@ -767,4 +767,17 @@ suite('SnippetParser', () => { assert.equal((variable.transform!.children[0]).ifValue, 'import { hello } from world'); assert.equal((variable.transform!.children[0]).elseValue, undefined); }); + + test('Snippet escape backslashes inside conditional insertion variable replacement #80394', function () { + + let snippet = new SnippetParser().parse('${CURRENT_YEAR/(.+)/${1:+\\\\}/}'); + let variable = snippet.children[0]; + assert.equal(snippet.children.length, 1); + assert.ok(variable instanceof Variable); + assert.ok(variable.transform); + assert.equal(variable.transform!.children.length, 1); + assert.ok(variable.transform!.children[0] instanceof FormatString); + assert.equal((variable.transform!.children[0]).ifValue, '\\'); + assert.equal((variable.transform!.children[0]).elseValue, undefined); + }); }); From 314d67c15bd796c70cc5d7eca5ccf9544c4756c5 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Sat, 28 Sep 2019 15:32:52 -0500 Subject: [PATCH 009/435] :lipstick: --- src/vs/editor/contrib/snippet/snippetParser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetParser.ts b/src/vs/editor/contrib/snippet/snippetParser.ts index 5e666885a67..7823405f14e 100644 --- a/src/vs/editor/contrib/snippet/snippetParser.ts +++ b/src/vs/editor/contrib/snippet/snippetParser.ts @@ -664,7 +664,7 @@ export class SnippetParser { } private _until(type: TokenType): false | string { - let start = this._token; + const start = this._token; while (this._token.type !== type) { if (this._token.type === TokenType.EOF) { return false; @@ -678,7 +678,7 @@ export class SnippetParser { } this._token = this._scanner.next(); } - let value = this._scanner.value.substring(start.pos, this._token.pos).replace(/\\(\$|}|\\)/g, '$1'); + const value = this._scanner.value.substring(start.pos, this._token.pos).replace(/\\(\$|}|\\)/g, '$1'); this._token = this._scanner.next(); return value; } From 665ac1da3328f6c3578aa97c368784ce898a4789 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 30 Sep 2019 17:20:41 +0200 Subject: [PATCH 010/435] Clean up Gesture.addTarget --- src/vs/editor/browser/viewParts/minimap/minimap.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 8914672b297..b32b8d83775 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -456,6 +456,7 @@ export class Minimap extends ViewPart { private readonly _mouseDownListener: IDisposable; private readonly _sliderMouseMoveMonitor: GlobalMouseMoveMonitor; private readonly _sliderMouseDownListener: IDisposable; + private readonly _gestureDisposable: IDisposable; private readonly _sliderTouchStartListener: IDisposable; private readonly _sliderTouchMoveListener: IDisposable; private readonly _sliderTouchEndListener: IDisposable; @@ -576,7 +577,7 @@ export class Minimap extends ViewPart { } }); - Gesture.addTarget(this._domNode.domNode); + this._gestureDisposable = Gesture.addTarget(this._domNode.domNode); this._sliderTouchStartListener = dom.addDisposableListener(this._domNode.domNode, EventType.Start, (e: GestureEvent) => { e.preventDefault(); e.stopPropagation(); @@ -615,6 +616,7 @@ export class Minimap extends ViewPart { this._mouseDownListener.dispose(); this._sliderMouseMoveMonitor.dispose(); this._sliderMouseDownListener.dispose(); + this._gestureDisposable.dispose(); this._sliderTouchStartListener.dispose(); this._sliderTouchMoveListener.dispose(); this._sliderTouchEndListener.dispose(); From 22caeb97a487fb87ef05a2d80fb61997d624a4e8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 17:42:37 +0200 Subject: [PATCH 011/435] handle v6 ip addresses in remote-resources rewrite --- src/vs/base/common/network.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index 7d525614421..70093426625 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts @@ -92,7 +92,10 @@ class RemoteAuthoritiesImpl { return this._delegate(uri); } const authority = uri.authority; - const host = this._hosts[authority]; + let host = this._hosts[authority]; + if (host.indexOf(':') !== -1) { + host = `[${host}]`; + } const port = this._ports[authority]; const connectionToken = this._connectionTokens[authority]; return URI.from({ From 5f8dec837f3cb6688e04319d55e7456c22b8ae76 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 30 Sep 2019 17:51:18 +0200 Subject: [PATCH 012/435] enable auth by config --- src/vs/platform/auth/common/authTokenService.ts | 4 +++- src/vs/platform/userDataSync/common/userDataSync.ts | 6 ++++++ .../contrib/relauncher/browser/relauncher.contribution.ts | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/auth/common/authTokenService.ts b/src/vs/platform/auth/common/authTokenService.ts index 3f2878311af..322ecfb2b09 100644 --- a/src/vs/platform/auth/common/authTokenService.ts +++ b/src/vs/platform/auth/common/authTokenService.ts @@ -8,6 +8,7 @@ import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { Disposable } from 'vs/base/common/lifecycle'; import { IProductService } from 'vs/platform/product/common/productService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; const SERVICE_NAME = 'VS Code'; const ACCOUNT = 'MyAccount'; @@ -23,9 +24,10 @@ export class AuthTokenService extends Disposable implements IAuthTokenService { constructor( @ICredentialsService private readonly credentialsService: ICredentialsService, @IProductService productService: IProductService, + @IConfigurationService configurationService: IConfigurationService, ) { super(); - if (productService.settingsSyncStoreUrl) { + if (productService.settingsSyncStoreUrl && configurationService.getValue('configurationSync.enableAuth')) { this._status = AuthTokenStatus.Inactive; this.getToken().then(token => { if (token) { diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 942a4a3b318..6578b2a30b1 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -63,6 +63,12 @@ export function registerConfiguration(): IDisposable { $ref: ignoredSettingsSchemaId, additionalProperties: true, uniqueItems: true + }, + 'configurationSync.enableAuth': { + 'type': 'boolean', + description: localize('configurationSync.enableAuth', "Enables authentication and requires VS Code restart when changed"), + 'default': false, + 'scope': ConfigurationScope.APPLICATION } } }); diff --git a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts index 7384ae902f0..9f01d0a2445 100644 --- a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts +++ b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts @@ -26,6 +26,7 @@ interface IConfiguration extends IWindowsConfiguration { telemetry: { enableCrashReporter: boolean }; workbench: { list: { horizontalScrolling: boolean } }; debug: { console: { wordWrap: boolean } }; + configurationSync: { enableAuth: boolean }; } export class SettingsChangeRelauncher extends Disposable implements IWorkbenchContribution { @@ -38,6 +39,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo private enableCrashReporter: boolean | undefined; private treeHorizontalScrolling: boolean | undefined; private debugConsoleWordWrap: boolean | undefined; + private enableConfigSyncAuth: boolean | undefined; constructor( @IHostService private readonly hostService: IHostService, @@ -105,6 +107,12 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo } } + // Configuration Sync Auth + if (config.configurationSync && typeof config.configurationSync.enableAuth === 'boolean' && config.configurationSync.enableAuth !== this.enableConfigSyncAuth) { + this.enableConfigSyncAuth = config.configurationSync.enableAuth; + changed = true; + } + // Notify only when changed and we are the focused window (avoids notification spam across windows) if (notify && changed) { this.doConfirm( From eb5ec0fd2a9f22a2cac3ba672c2ed9e9b04385b6 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Mon, 30 Sep 2019 08:18:37 -0700 Subject: [PATCH 013/435] Suggest linebreak. Fix #79840 --- src/vs/base/common/htmlContent.ts | 5 ++++- .../base/test/common/markdownString.test.ts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/vs/base/test/common/markdownString.test.ts diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index ac7c8ed3a91..fee84c57bf6 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -23,7 +23,10 @@ export class MarkdownString implements IMarkdownString { appendText(value: string): MarkdownString { // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash - this.value += value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'); + this.value += value + .replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') + .replace('\n', '\n\n'); + return this; } diff --git a/src/vs/base/test/common/markdownString.test.ts b/src/vs/base/test/common/markdownString.test.ts new file mode 100644 index 00000000000..69d33de8f17 --- /dev/null +++ b/src/vs/base/test/common/markdownString.test.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. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { MarkdownString } from 'vs/base/common/htmlContent'; + +suite('markdownString', () => { + + test('escape', () => { + + const mds = new MarkdownString(); + + mds.appendText('# foo\n*bar*'); + + assert.equal(mds.value, '\\# foo\n\n\\*bar\\*'); + }); +}); From d26bc6e7d5859167312b9be3ff728b140f1cf857 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 10:19:19 -0700 Subject: [PATCH 014/435] Fix #81662 --- src/vs/workbench/contrib/files/browser/views/emptyView.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index e7e9ecf5f61..8b54ec0abe8 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -54,6 +54,10 @@ export class EmptyView extends ViewletPanel { } renderHeader(container: HTMLElement): void { + const twisties = document.createElement('div'); + DOM.addClasses(twisties, 'twisties', 'codicon', 'codicon-chevron-right'); + container.appendChild(twisties); + const titleContainer = document.createElement('div'); DOM.addClass(titleContainer, 'title'); container.appendChild(titleContainer); From 3611cc7d07ed03a66dc90212aade88d80153a11c Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 10:23:48 -0700 Subject: [PATCH 015/435] Show collapse icon in Problems panel --- src/vs/workbench/contrib/markers/browser/markersPanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/markers/browser/markersPanel.ts b/src/vs/workbench/contrib/markers/browser/markersPanel.ts index 2c2edfc7e3e..c509e857100 100644 --- a/src/vs/workbench/contrib/markers/browser/markersPanel.ts +++ b/src/vs/workbench/contrib/markers/browser/markersPanel.ts @@ -117,7 +117,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { this.rangeHighlightDecorations = this._register(this.instantiationService.createInstance(RangeHighlightDecorations)); // actions - this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action collapse-all', true, async () => this.collapseAll())); + this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action codicon-collapse-all', true, async () => this.collapseAll())); this.filterAction = this._register(this.instantiationService.createInstance(MarkersFilterAction, { filterText: this.panelState['filter'] || '', filterHistory: this.panelState['filterHistory'] || [], useFilesExclude: !!this.panelState['useFilesExclude'] })); } From 83cd86bb36021ad5d8d4cbeb52e456dec12d20cd Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 10:45:44 -0700 Subject: [PATCH 016/435] Fix #81649, show collapse icon in debug viewlet --- .../files/browser/media/collapse-all-dark.svg | 4 ++++ .../contrib/files/browser/media/collapse-all-hc.svg | 4 ++++ .../files/browser/media/collapse-all-light.svg | 4 ++++ .../contrib/files/browser/media/explorerviewlet.css | 13 +++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 src/vs/workbench/contrib/files/browser/media/collapse-all-dark.svg create mode 100644 src/vs/workbench/contrib/files/browser/media/collapse-all-hc.svg create mode 100644 src/vs/workbench/contrib/files/browser/media/collapse-all-light.svg diff --git a/src/vs/workbench/contrib/files/browser/media/collapse-all-dark.svg b/src/vs/workbench/contrib/files/browser/media/collapse-all-dark.svg new file mode 100644 index 00000000000..4862c55dbeb --- /dev/null +++ b/src/vs/workbench/contrib/files/browser/media/collapse-all-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/workbench/contrib/files/browser/media/collapse-all-hc.svg b/src/vs/workbench/contrib/files/browser/media/collapse-all-hc.svg new file mode 100644 index 00000000000..05f920b29b6 --- /dev/null +++ b/src/vs/workbench/contrib/files/browser/media/collapse-all-hc.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/workbench/contrib/files/browser/media/collapse-all-light.svg b/src/vs/workbench/contrib/files/browser/media/collapse-all-light.svg new file mode 100644 index 00000000000..6359b42e623 --- /dev/null +++ b/src/vs/workbench/contrib/files/browser/media/collapse-all-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css index 86fd93fa0d3..976b42abd13 100644 --- a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css @@ -163,3 +163,16 @@ .hc-black .monaco-workbench .explorer-viewlet .editor-group { line-height: 20px; } + +/* TODO @misolori convert these to use icon font, for the debug viewlet */ +.monaco-workbench .explorer-action.collapse-explorer { + background: url("collapse-all-light.svg") 50% no-repeat; +} + +.vs-dark .monaco-workbench .explorer-action.collapse-explorer { + background: url("collapse-all-dark.svg") 50% no-repeat; +} + +.hc-black .monaco-workbench .explorer-action.collapse-explorer { + background: url("collapse-all-hc.svg") 50% no-repeat; +} From 2c704846d66e5f4741d668e37725101197181855 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 10:46:24 -0700 Subject: [PATCH 017/435] Show correct icon in HC mode for adding breakpoints --- src/vs/workbench/contrib/debug/browser/media/debugViewlet.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css index 2ed61ccf6b0..f49d190d4b0 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css @@ -445,7 +445,8 @@ background: url('add-dark.svg') center center no-repeat; } -.hc-black .debug-viewlet .debug-action.add-watch-expression { +.hc-black .debug-viewlet .debug-action.add-watch-expression, +.hc-black .debug-viewlet .debug-action.add-function-breakpoint { background: url('add-hc.svg') center center no-repeat; } From 889d69688b279ff8afe41358a8d236368af38bd8 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 11:34:22 -0700 Subject: [PATCH 018/435] Update Octicons and cgmanifest --- cgmanifest.json | 4 ++-- .../ui/octiconLabel/octicons/octicons.css | 2 +- .../ui/octiconLabel/octicons/octicons.ttf | Bin 35464 -> 35428 bytes 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cgmanifest.json b/cgmanifest.json index d26f37b6204..c16d88b5991 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -98,11 +98,11 @@ "git": { "name": "vscode-octicons-font", "repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font", - "commitHash": "415cd5b42ab699b6b46c0bf011ada0a2ae50bfb4" + "commitHash": "4cbf2bd35cf0084eabd47d322cc58339fd7743cf" } }, "license": "MIT", - "version": "1.3.1" + "version": "1.3.2" }, { "component": { diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css index 2305d04890f..154a2251587 100644 --- a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css +++ b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css @@ -1,6 +1,6 @@ @font-face { font-family: "octicons"; - src: url("./octicons.ttf?628f71ee09945d25ba5fceb0c17f7b0f") format("truetype"); + src: url("./octicons.ttf?1829db8570ee0fa5a4bef3bb41d5f62e") format("truetype"); } .octicon, .mega-octicon { diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf index 09468d3324453a2c7e5ea5a6422fffef725ec38a..90550092a65dcf320264753b16d5ac9217e37f6e 100644 GIT binary patch delta 308 zcmeB}%JgIk(*y^RtIB-w3=F~^3=BCv8L5dWV#Ve?6GL=Z;y4`-Ol(mWyu!f1Bvz1L zT+;sK+(QP2#y1mp7|2XMW6%)KZ}XLboB0I;5Zv7UOAJPDW?{T8STCYxpq8N4qRyc1 zqJB;NhlYa2GEElE9?d^mQCi!yUTLdoPtZQ5{Xs`VCrxL8u7GZg?gKpqy#&2$`u_}U z45k>oFmy94Fg#%Rz(~kQ&uEg-7vnX?A554`L`>97EKC|qZkWcIZZLgjreo#?w3zw- z|NjBZ&CI3@Dh&Dz-V6+zql8a;dohCC#PpuYia~;bfze2gMTCz+jo7kc(_=ACgNvt5h zxTO8dxrYo4O#%~l7|669I+GF4Z}XLboB0I;5Zv4}xeZ2dW?{T8Sg)q$q*kOhO?93v77Bm0< z|384anc0*eq@iB_XF`A3; zF)HaXn%FTK$uX(}v8W+Xj`532v9oh=2Z(sC;~n9x111*h`|IiXyFn#@vcGhoGCJN3 cdj9%AX`odg` Date: Mon, 30 Sep 2019 11:28:25 -0700 Subject: [PATCH 019/435] Polish css.completion.completePropertyWithSemicolon doc --- extensions/css-language-features/package.nls.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/css-language-features/package.nls.json b/extensions/css-language-features/package.nls.json index 550820976d7..9126d9adf5e 100644 --- a/extensions/css-language-features/package.nls.json +++ b/extensions/css-language-features/package.nls.json @@ -4,7 +4,7 @@ "css.title": "CSS", "css.customData.desc": "A list of relative file paths pointing to JSON files following the [custom data format](https://github.com/Microsoft/vscode-css-languageservice/blob/master/docs/customData.md).\n\nVS Code loads custom data on startup to enhance its CSS support for the custom CSS properties, at directives, pseudo classes and pseudo elements you specify in the JSON files.\n\nThe file paths are relative to workspace and only workspace folder settings are considered.", "css.completion.triggerPropertyValueCompletion.desc": "By default, VS Code triggers property value completion after selecting a CSS property. Use this setting to disable this behavior.", - "css.completion.completePropertyWithSemicolon.desc": "Insert semicolon at end when completing CSS properties", + "css.completion.completePropertyWithSemicolon.desc": "Insert semicolon at end of line when completing CSS properties", "css.lint.argumentsInColorFunction.desc": "Invalid number of parameters.", "css.lint.boxModel.desc": "Do not use `width` or `height` when using `padding` or `border`.", "css.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties.", From 3f3a9e30db19282e34417935293b5642a2295cc7 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 11:42:36 -0700 Subject: [PATCH 020/435] Fix #81536, center git decorations --- .../services/decorations/browser/decorationsService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index a10d68678a5..0d63a904f6c 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -75,9 +75,10 @@ class DecorationRule { } // bubble badge + // TODO @misolori update bubble badge to use class name instead of unicode createCSSRule( `.${this.bubbleBadgeClassName}::after`, - `content: "\uf052"; color: ${getColor(theme, color)}; font-family: octicons; font-size: 14px; padding-right: 14px; opacity: 0.4;`, + `content: "\uf052"; color: ${getColor(theme, color)}; font-family: octicons; font-size: 14px; padding-right: 10px; opacity: 0.4;`, element ); } From a5745f5042755e7edf7ca28ecb997a83716de116 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 21:03:13 +0200 Subject: [PATCH 021/435] [folding] Support single shortcut for toggling fold/unfold. Fixes #18549 --- src/vs/editor/contrib/folding/folding.ts | 27 ++++++++++++++++++- src/vs/editor/contrib/folding/foldingModel.ts | 20 ++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index f0ae51e1955..6806e903e67 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -14,7 +14,7 @@ import { ScrollType, IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; -import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType } from 'vs/editor/contrib/folding/foldingModel'; +import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType, toggleCollapseState } from 'vs/editor/contrib/folding/foldingModel'; import { FoldingDecorationProvider } from './foldingDecorations'; import { FoldingRegions, FoldingRegion } from './foldingRanges'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -656,6 +656,30 @@ class FoldAction extends FoldingAction { } } + +class ToggleFoldAction extends FoldingAction { + + constructor() { + super({ + id: 'editor.toggleFold', + label: nls.localize('toggleFoldAction.label', "Toggle Fold"), + alias: 'Toggle Fold', + precondition: CONTEXT_FOLDING_ENABLED, + kbOpts: { + kbExpr: EditorContextKeys.editorTextFocus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K), + weight: KeybindingWeight.EditorContrib + } + }); + } + + invoke(_foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { + let selectedLines = this.getSelectedLines(editor); + toggleCollapseState(foldingModel, 1, selectedLines); + } +} + + class FoldRecursivelyAction extends FoldingAction { constructor() { @@ -842,6 +866,7 @@ registerEditorAction(UnfoldAllAction); registerEditorAction(FoldAllBlockCommentsAction); registerEditorAction(FoldAllRegionsAction); registerEditorAction(UnfoldAllRegionsAction); +registerEditorAction(ToggleFoldAction); for (let i = 1; i <= 7; i++) { registerInstantiatedEditorAction( diff --git a/src/vs/editor/contrib/folding/foldingModel.ts b/src/vs/editor/contrib/folding/foldingModel.ts index 15cc62d2098..44feb79cdf2 100644 --- a/src/vs/editor/contrib/folding/foldingModel.ts +++ b/src/vs/editor/contrib/folding/foldingModel.ts @@ -242,6 +242,26 @@ export class FoldingModel { } +/** + * Collapse or expand the regions at the given locations + * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels. + * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model. + */ +export function toggleCollapseState(foldingModel: FoldingModel, levels: number, lineNumbers: number[]) { + let toToggle: FoldingRegion[] = []; + for (let lineNumber of lineNumbers) { + let region = foldingModel.getRegionAtLine(lineNumber); + if (region) { + const doCollapse = !region.isCollapsed; + toToggle.push(region); + if (levels > 1) { + let regionsInside = foldingModel.getRegionsInside(region, (r, level: number) => r.isCollapsed !== doCollapse && level < levels); + toToggle.push(...regionsInside); + } + } + } + foldingModel.toggleCollapseState(toToggle); +} /** From b8a75a33dd67ff1ced462e94ba5a2c5b409c91c7 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 12:17:57 -0700 Subject: [PATCH 022/435] Fix #81573, show beak in status bar --- .../workbench/browser/parts/statusbar/media/statusbarpart.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css index 92c49501535..b6c02890789 100644 --- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css +++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css @@ -10,6 +10,7 @@ height: 22px; font-size: 12px; display: flex; + overflow: visible; } .monaco-workbench .part.statusbar.status-border-top::after { @@ -52,7 +53,7 @@ .monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { content: ''; position: absolute; - left: calc(50% - 8px); /* 3px (margin) + 5px (padding) = 8px */ + left: calc(50% - 9px); /* 3px (margin) + 5px (padding) + 1px (icon) = 9px */ top: -5px; border-bottom-width: 5px; border-bottom-style: solid; From ecba37c6ef3aab85b7a9b15afb3610bbe4eaac8c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 22:55:31 +0200 Subject: [PATCH 023/435] update css service/server --- extensions/css-language-features/package.json | 4 +- .../css-language-features/server/package.json | 6 +- .../server/src/cssServerMain.ts | 4 +- .../server/src/pathCompletion.ts | 2 +- .../server/src/test/completion.test.ts | 26 +- .../server/src/test/links.test.ts | 6 +- .../server/src/utils/documentContext.ts | 2 +- .../css-language-features/server/yarn.lock | 62 +- extensions/css-language-features/yarn.lock | 556 ++++++++++++++++-- 9 files changed, 549 insertions(+), 119 deletions(-) diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 1dbd7608495..734deb0f2e3 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -759,11 +759,11 @@ ] }, "dependencies": { - "vscode-languageclient": "^5.3.0-next.6", + "vscode-languageclient": "^6.0.0-next.1", "vscode-nls": "^4.1.1" }, "devDependencies": { "@types/node": "^10.14.8", - "mocha": "^5.2.0" + "mocha": "^6.1.4" } } diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index def7def57c2..0616cb6f278 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,15 +9,15 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.8", - "vscode-languageserver": "^5.3.0-next.8" + "vscode-css-languageservice": "^4.0.3-next.9", + "vscode-languageserver": "^6.0.0-next.1" }, "devDependencies": { "@types/mocha": "2.2.33", "@types/node": "^10.14.8", "glob": "^7.1.4", "mocha": "^6.1.4", - "mocha-junit-reporter": "^1.23.0", + "mocha-junit-reporter": "^1.23.1", "mocha-multi-reporters": "^1.1.7" }, "scripts": { diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index a1dee46c523..0856a649326 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -6,7 +6,7 @@ import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, ServerCapabilities, ConfigurationRequest, WorkspaceFolder } from 'vscode-languageserver'; -import URI from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { TextDocument, CompletionList, Position } from 'vscode-languageserver-types'; import { stat as fsStat } from 'fs'; @@ -390,4 +390,4 @@ connection.onSelectionRanges((params, token) => { // Listen on the connection -connection.listen(); \ No newline at end of file +connection.listen(); diff --git a/extensions/css-language-features/server/src/pathCompletion.ts b/extensions/css-language-features/server/src/pathCompletion.ts index aafed82b513..6862f28e034 100644 --- a/extensions/css-language-features/server/src/pathCompletion.ts +++ b/extensions/css-language-features/server/src/pathCompletion.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as fs from 'fs'; -import URI from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { TextDocument, CompletionList, CompletionItemKind, CompletionItem, TextEdit, Range, Position } from 'vscode-languageserver-types'; import { WorkspaceFolder } from 'vscode-languageserver'; diff --git a/extensions/css-language-features/server/src/test/completion.test.ts b/extensions/css-language-features/server/src/test/completion.test.ts index 3a832600355..d8230ba2922 100644 --- a/extensions/css-language-features/server/src/test/completion.test.ts +++ b/extensions/css-language-features/server/src/test/completion.test.ts @@ -5,7 +5,7 @@ import 'mocha'; import * as assert from 'assert'; import * as path from 'path'; -import Uri from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { TextDocument, CompletionList } from 'vscode-languageserver-types'; import { WorkspaceFolder } from 'vscode-languageserver-protocol'; import { getPathCompletionParticipant } from '../pathCompletion'; @@ -60,8 +60,8 @@ suite('Completions', () => { } test('CSS url() Path completion', function () { - let testUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); - let folders = [{ name: 'x', uri: Uri.file(path.resolve(__dirname, '../../test')).toString() }]; + let testUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); + let folders = [{ name: 'x', uri: URI.file(path.resolve(__dirname, '../../test')).toString() }]; assertCompletions('html { background-image: url("./|")', { items: [ @@ -119,8 +119,8 @@ suite('Completions', () => { }); test('CSS url() Path Completion - Unquoted url', function () { - let testUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); - let folders = [{ name: 'x', uri: Uri.file(path.resolve(__dirname, '../../test')).toString() }]; + let testUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); + let folders = [{ name: 'x', uri: URI.file(path.resolve(__dirname, '../../test')).toString() }]; assertCompletions('html { background-image: url(./|)', { items: [ @@ -148,8 +148,8 @@ suite('Completions', () => { }); test('CSS @import Path completion', function () { - let testUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); - let folders = [{ name: 'x', uri: Uri.file(path.resolve(__dirname, '../../test')).toString() }]; + let testUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); + let folders = [{ name: 'x', uri: URI.file(path.resolve(__dirname, '../../test')).toString() }]; assertCompletions(`@import './|'`, { items: [ @@ -171,8 +171,8 @@ suite('Completions', () => { * For SCSS, `@import 'foo';` can be used for importing partial file `_foo.scss` */ test('SCSS @import Path completion', function () { - let testCSSUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); - let folders = [{ name: 'x', uri: Uri.file(path.resolve(__dirname, '../../test')).toString() }]; + let testCSSUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); + let folders = [{ name: 'x', uri: URI.file(path.resolve(__dirname, '../../test')).toString() }]; /** * We are in a CSS file, so no special treatment for SCSS partial files @@ -184,7 +184,7 @@ suite('Completions', () => { ] }, testCSSUri, folders); - let testSCSSUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/scss/main.scss')).toString(); + let testSCSSUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/scss/main.scss')).toString(); assertCompletions(`@import './|'`, { items: [ { label: '_foo.scss', resultText: `@import './foo'` } @@ -193,12 +193,12 @@ suite('Completions', () => { }); test('Completion should ignore files/folders starting with dot', function () { - let testUri = Uri.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); - let folders = [{ name: 'x', uri: Uri.file(path.resolve(__dirname, '../../test')).toString() }]; + let testUri = URI.file(path.resolve(__dirname, '../../test/pathCompletionFixtures/about/about.css')).toString(); + let folders = [{ name: 'x', uri: URI.file(path.resolve(__dirname, '../../test')).toString() }]; assertCompletions('html { background-image: url("../|")', { count: 4 }, testUri, folders); }); -}); \ No newline at end of file +}); diff --git a/extensions/css-language-features/server/src/test/links.test.ts b/extensions/css-language-features/server/src/test/links.test.ts index bce7a11bc8a..a2a13361016 100644 --- a/extensions/css-language-features/server/src/test/links.test.ts +++ b/extensions/css-language-features/server/src/test/links.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'mocha'; import * as assert from 'assert'; -import Uri from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { resolve } from 'path'; import { TextDocument, DocumentLink } from 'vscode-languageserver-types'; import { WorkspaceFolder } from 'vscode-languageserver-protocol'; @@ -54,7 +54,7 @@ suite('Links', () => { } function getTestResource(path: string) { - return Uri.file(resolve(__dirname, '../../test/linksTestFixtures', path)).toString(); + return URI.file(resolve(__dirname, '../../test/linksTestFixtures', path)).toString(); } test('url links', function () { @@ -76,4 +76,4 @@ suite('Links', () => { [{ offset: 29, value: '"~foo/hello.html"', target: getTestResource('node_modules/foo/hello.html') }], testUri, folders ); }); -}); \ No newline at end of file +}); diff --git a/extensions/css-language-features/server/src/utils/documentContext.ts b/extensions/css-language-features/server/src/utils/documentContext.ts index 494ff395e9d..7c488a4e372 100644 --- a/extensions/css-language-features/server/src/utils/documentContext.ts +++ b/extensions/css-language-features/server/src/utils/documentContext.ts @@ -7,7 +7,7 @@ import { DocumentContext } from 'vscode-css-languageservice'; import { endsWith, startsWith } from '../utils/strings'; import * as url from 'url'; import { WorkspaceFolder } from 'vscode-languageserver'; -import URI from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { join, dirname } from 'path'; import { existsSync } from 'fs'; diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 9cda831e23b..08d99b91e27 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -479,10 +479,10 @@ mkdirp@0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -mocha-junit-reporter@^1.23.0: - version "1.23.0" - resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.0.tgz#c5ad7f10b5aa9a7cc6e169b6bf15baf2700266ca" - integrity sha512-pmpnEO4iDTmLfrT2RKqPsc5relG4crnDSGmXPuGogdda27A7kLujDNJV4EbTbXlVBCZXggN9rQYPEWMkOv4AAA== +mocha-junit-reporter@^1.23.1: + version "1.23.1" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.1.tgz#ba11519c0b967f404e4123dd69bc4ba022ab0f12" + integrity sha512-qeDvKlZyAH2YJE1vhryvjUQ06t2hcnwwu4k5Ddwn0GQINhgEYFhlGM0DwYCVUHq5cuo32qAW6HDsTHt7zz99Ng== dependencies: debug "^2.2.0" md5 "^2.1.0" @@ -781,41 +781,40 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.8: - version "4.0.3-next.8" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.8.tgz#0b81693b6ea9d10f78775a1dcad2c0f464fbde16" - integrity sha512-agBPPu86bPKIK5v6CFnWeBXN4jvnCzc67GZa/pvrIWeRdG7nvTu5Y2wYdwdesdpWzno9/5tfFEPp0KJbKQ4l+A== +vscode-css-languageservice@^4.0.3-next.9: + version "4.0.3-next.9" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.9.tgz#27e36bca98dc51cb99d4046fb84c99e00e629b2f" + integrity sha512-b1WQ+4/wFbgFTsmFyIQ8PjgD9M5dJBaBN67kAFMbyaavv7uemR2wuD6SiX1OsitmlVi3WEUtJZdLtka45r8dEw== dependencies: - vscode-languageserver-types "^3.15.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" -vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== -vscode-languageserver@^5.3.0-next.8: - version "5.3.0-next.8" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" - integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== +vscode-languageserver@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.1.tgz#4d71886d4a17d22eafc61b3a5fbf84e8e27c191f" + integrity sha512-LSF6bXoFeXfMPRNyqzI3yFX/kD2DzXBemqvyj1kDWNVraiWttm4xKF4YXsvJ7Z3s9sVt/Dpu3CFU3w61PGNZMg== dependencies: - vscode-languageserver-protocol "^3.15.0-next.6" + vscode-languageserver-protocol "^3.15.0-next.9" vscode-textbuffer "^1.0.0" - vscode-uri "^1.0.6" vscode-nls@^4.1.1: version "4.1.1" @@ -827,11 +826,6 @@ vscode-textbuffer@^1.0.0: resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== -vscode-uri@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" - integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== - vscode-uri@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 48f16a42fe5..cd8d040e9a3 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -7,6 +7,35 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -25,42 +54,143 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: - ms "2.0.0" + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -escape-string-regexp@1.0.5: +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +es-abstract@^1.5.1: + version "1.14.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" + integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.0.0" + string.prototype.trimright "^2.0.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -79,10 +209,22 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== inflight@^1.0.4: version "1.0.6" @@ -97,6 +239,73 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +is-buffer@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -116,27 +325,80 @@ mkdirp@0.5.1: dependencies: minimist "0.0.8" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== +mocha@^6.1.4: + version "6.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" + integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== dependencies: + ansi-colors "3.2.3" browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" + debug "3.2.6" diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.2" + find-up "3.0.0" + glob "7.1.3" growl "1.10.5" - he "1.1.1" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" minimatch "3.0.4" mkdirp "0.5.1" - supports-color "5.4.0" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" once@^1.3.0: version "1.4.0" @@ -145,55 +407,229 @@ once@^1.3.0: dependencies: wrappy "1" +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -semver@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" - integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== - -vscode-languageclient@^5.3.0-next.6: - version "5.3.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" - integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - semver "^5.5.0" - vscode-languageserver-protocol "^3.15.0-next.6" + has-flag "^3.0.0" -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== + +vscode-languageclient@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz#deca1743afd20da092e04e40ef73cedbbd978455" + integrity sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + semver "^6.3.0" + vscode-languageserver-protocol "^3.15.0-next.9" -vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== + dependencies: + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" + +vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== vscode-nls@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" From d6169488c37dd174b2d3315fdd1bb97d26f7cb4c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 22:58:18 +0200 Subject: [PATCH 024/435] update html server & service --- .../html-language-features/package.json | 2 +- .../server/package.json | 14 +- .../html-language-features/server/yarn.lock | 582 +++++++++++++++--- extensions/html-language-features/yarn.lock | 47 +- 4 files changed, 546 insertions(+), 99 deletions(-) diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 557fe83ca86..6d6781b9d50 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -197,7 +197,7 @@ }, "dependencies": { "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "^5.3.0-next.6", + "vscode-languageclient": "^6.0.0-next.1", "vscode-nls": "^4.1.1" }, "devDependencies": { diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index e6eca4275bf..fe5ae39087e 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,19 +9,19 @@ }, "main": "./out/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.8", - "vscode-html-languageservice": "^3.0.4-next.3", - "vscode-languageserver": "^5.3.0-next.8", - "vscode-languageserver-types": "3.15.0-next.2", + "vscode-css-languageservice": "^4.0.3-next.9", + "vscode-html-languageservice": "^3.0.4-next.4", + "vscode-languageserver": "^6.0.0-next.1", + "vscode-languageserver-types": "3.15.0-next.5", "vscode-nls": "^4.1.1", "vscode-uri": "^2.0.3" }, "devDependencies": { "@types/mocha": "2.2.33", "@types/node": "^10.14.8", - "glob": "^7.1.2", - "mocha": "^5.2.0", - "mocha-junit-reporter": "^1.17.0", + "glob": "^7.1.4", + "mocha": "^6.1.4", + "mocha-junit-reporter": "^1.23.1", "mocha-multi-reporters": "^1.1.7" }, "scripts": { diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index 7b9957f070d..ad45194dff7 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -12,11 +12,35 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -35,15 +59,45 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= concat-map@0.0.1: version "0.0.1" @@ -55,12 +109,12 @@ crypt@~0.0.1: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -debug@3.1.0, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: - ms "2.0.0" + ms "^2.1.1" debug@^2.2.0: version "2.6.9" @@ -69,25 +123,115 @@ debug@^2.2.0: dependencies: ms "2.0.0" +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -escape-string-regexp@1.0.5: +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +es-abstract@^1.5.1: + version "1.14.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" + integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.0.0" + string.prototype.trimright "^2.0.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -glob@7.1.2, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -106,10 +250,22 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== inflight@^1.0.4: version "1.0.6" @@ -129,11 +285,78 @@ is-buffer@~1.1.1: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash@^4.16.4: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + md5@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" @@ -162,10 +385,10 @@ mkdirp@0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -mocha-junit-reporter@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz#2e5149ed40fc5d2e3ca71e42db5ab1fec9c6d85c" - integrity sha1-LlFJ7UD8XS48px5C21qx/snG2Fw= +mocha-junit-reporter@^1.23.1: + version "1.23.1" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.1.tgz#ba11519c0b967f404e4123dd69bc4ba022ab0f12" + integrity sha512-qeDvKlZyAH2YJE1vhryvjUQ06t2hcnwwu4k5Ddwn0GQINhgEYFhlGM0DwYCVUHq5cuo32qAW6HDsTHt7zz99Ng== dependencies: debug "^2.2.0" md5 "^2.1.0" @@ -181,28 +404,86 @@ mocha-multi-reporters@^1.1.7: debug "^3.1.0" lodash "^4.16.4" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== +mocha@^6.1.4: + version "6.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" + integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== dependencies: + ansi-colors "3.2.3" browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" + debug "3.2.6" diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.2" + find-up "3.0.0" + glob "7.1.3" growl "1.10.5" - he "1.1.1" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" minimatch "3.0.4" mkdirp "0.5.1" - supports-color "5.4.0" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -210,11 +491,93 @@ once@^1.3.0: dependencies: wrappy "1" +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -222,57 +585,75 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.8: - version "4.0.3-next.8" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.8.tgz#0b81693b6ea9d10f78775a1dcad2c0f464fbde16" - integrity sha512-agBPPu86bPKIK5v6CFnWeBXN4jvnCzc67GZa/pvrIWeRdG7nvTu5Y2wYdwdesdpWzno9/5tfFEPp0KJbKQ4l+A== +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - vscode-languageserver-types "^3.15.0-next.2" + has-flag "^3.0.0" + +vscode-css-languageservice@^4.0.3-next.9: + version "4.0.3-next.9" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.9.tgz#27e36bca98dc51cb99d4046fb84c99e00e629b2f" + integrity sha512-b1WQ+4/wFbgFTsmFyIQ8PjgD9M5dJBaBN67kAFMbyaavv7uemR2wuD6SiX1OsitmlVi3WEUtJZdLtka45r8dEw== + dependencies: + vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-html-languageservice@^3.0.4-next.3: - version "3.0.4-next.3" - resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.3.tgz#7a0fc33aae846165b157acbb8b133cc3fcf2ca0d" - integrity sha512-PGIcKFxqsvVMv51QWreuQx9LhN43Vzhgl8RYI8CcWThjl+J8uUKImjwAWq9zndOiiRUPF2Zk7zME/dMIis1hOw== +vscode-html-languageservice@^3.0.4-next.4: + version "3.0.4-next.4" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.4.tgz#e7cfd9429feb6e212606dee6de49f54b9f1449da" + integrity sha512-r8FgQIunfA6gq7LxJ7/iD8O6JHgpQeEhy8IfTiQNlKSsWcSBXubn4hdUgjHYWo+On2CW9ZIQLdle/9Xg4xh3aw== dependencies: - vscode-languageserver-types "^3.15.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" -vscode-languageserver-types@3.15.0-next.2, vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-types@3.15.0-next.5, vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== -vscode-languageserver@^5.3.0-next.8: - version "5.3.0-next.8" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" - integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== +vscode-languageserver@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.1.tgz#4d71886d4a17d22eafc61b3a5fbf84e8e27c191f" + integrity sha512-LSF6bXoFeXfMPRNyqzI3yFX/kD2DzXBemqvyj1kDWNVraiWttm4xKF4YXsvJ7Z3s9sVt/Dpu3CFU3w61PGNZMg== dependencies: - vscode-languageserver-protocol "^3.15.0-next.6" + vscode-languageserver-protocol "^3.15.0-next.9" vscode-textbuffer "^1.0.0" - vscode-uri "^1.0.6" vscode-nls@^4.1.1: version "4.1.1" @@ -284,16 +665,39 @@ vscode-textbuffer@^1.0.0: resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== -vscode-uri@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" - integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== - vscode-uri@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw== +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -303,3 +707,41 @@ xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index 21d801f04a0..195143d17dd 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -28,11 +28,16 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -semver@^5.3.0, semver@^5.5.0: +semver@^5.3.0: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + vscode-extension-telemetry@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" @@ -40,31 +45,31 @@ vscode-extension-telemetry@0.1.1: dependencies: applicationinsights "1.0.8" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== -vscode-languageclient@^5.3.0-next.6: - version "5.3.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" - integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== +vscode-languageclient@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz#deca1743afd20da092e04e40ef73cedbbd978455" + integrity sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg== dependencies: - semver "^5.5.0" - vscode-languageserver-protocol "^3.15.0-next.6" + semver "^6.3.0" + vscode-languageserver-protocol "^3.15.0-next.9" -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" -vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== vscode-nls@^4.1.1: version "4.1.1" From 14654091259a73fd2433896e55263d41921a740f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 22:58:40 +0200 Subject: [PATCH 025/435] update json server & service --- .../json-language-features/package.json | 2 +- .../server/package.json | 4 +- .../json-language-features/server/yarn.lock | 54 +++++++++---------- extensions/json-language-features/yarn.lock | 48 ++++++++--------- 4 files changed, 51 insertions(+), 57 deletions(-) diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index 167583302c2..cc61c9163c5 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -104,7 +104,7 @@ "dependencies": { "request-light": "^0.2.4", "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "^5.3.0-next.6", + "vscode-languageclient": "^6.0.0-next.1", "vscode-nls": "^4.1.1" }, "devDependencies": { diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 28c46483250..3559b36e9aa 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -14,8 +14,8 @@ "dependencies": { "jsonc-parser": "^2.1.1", "request-light": "^0.2.4", - "vscode-json-languageservice": "^3.3.4", - "vscode-languageserver": "^5.3.0-next.8", + "vscode-json-languageservice": "^3.3.5", + "vscode-languageserver": "^6.0.0-next.1", "vscode-nls": "^4.1.1", "vscode-uri": "^2.0.3" }, diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index 8230b9546bc..0ceb7ddcb1e 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -73,42 +73,41 @@ request-light@^0.2.4: https-proxy-agent "^2.2.1" vscode-nls "^4.0.0" -vscode-json-languageservice@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.4.tgz#4ff67580491d3a5dc469f4a78643f20adff0278d" - integrity sha512-/nuI4uDBfxyVyeGtBdYwP/tIaXYKOoymUOSozYKLzsmrDmu555gZpzc11LrARa96z92wSaa5hfjTtNMAoM2mxw== +vscode-json-languageservice@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.5.tgz#e222e8391beeb23cfa40cf17fd57d1594d295fc7" + integrity sha512-Le6SG5aRdrRc5jVeVMRkYbGH9rrVaZHCW0Oa8zCFQ0T8viUud9qdZ29lSv5NPNLwTB8mn4pYucFyyEPM2YWvLA== dependencies: jsonc-parser "^2.1.1" - vscode-languageserver-types "^3.15.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" -vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== -vscode-languageserver@^5.3.0-next.8: - version "5.3.0-next.8" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" - integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== +vscode-languageserver@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.1.tgz#4d71886d4a17d22eafc61b3a5fbf84e8e27c191f" + integrity sha512-LSF6bXoFeXfMPRNyqzI3yFX/kD2DzXBemqvyj1kDWNVraiWttm4xKF4YXsvJ7Z3s9sVt/Dpu3CFU3w61PGNZMg== dependencies: - vscode-languageserver-protocol "^3.15.0-next.6" + vscode-languageserver-protocol "^3.15.0-next.9" vscode-textbuffer "^1.0.0" - vscode-uri "^1.0.6" vscode-nls@^4.0.0: version "4.0.0" @@ -125,11 +124,6 @@ vscode-textbuffer@^1.0.0: resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== -vscode-uri@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" - integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== - vscode-uri@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index fdc89dd7cf1..b3804735a74 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -101,10 +101,10 @@ semver@^5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" - integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== vscode-extension-telemetry@0.1.1: version "0.1.1" @@ -113,31 +113,31 @@ vscode-extension-telemetry@0.1.1: dependencies: applicationinsights "1.0.8" -vscode-jsonrpc@^4.1.0-next.2: - version "4.1.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" - integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== +vscode-jsonrpc@^5.0.0-next.2: + version "5.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca" + integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg== -vscode-languageclient@^5.3.0-next.6: - version "5.3.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" - integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== +vscode-languageclient@^6.0.0-next.1: + version "6.0.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz#deca1743afd20da092e04e40ef73cedbbd978455" + integrity sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg== dependencies: - semver "^5.5.0" - vscode-languageserver-protocol "^3.15.0-next.6" + semver "^6.3.0" + vscode-languageserver-protocol "^3.15.0-next.9" -vscode-languageserver-protocol@^3.15.0-next.6: - version "3.15.0-next.6" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" - integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== +vscode-languageserver-protocol@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30" + integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g== dependencies: - vscode-jsonrpc "^4.1.0-next.2" - vscode-languageserver-types "^3.15.0-next.2" + vscode-jsonrpc "^5.0.0-next.2" + vscode-languageserver-types "^3.15.0-next.5" -vscode-languageserver-types@^3.15.0-next.2: - version "3.15.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" - integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== +vscode-languageserver-types@^3.15.0-next.5: + version "3.15.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b" + integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw== vscode-nls@^4.0.0: version "4.0.0" From 74ac7b852097abd467cdd2f21b5d5bb7383477d5 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Sep 2019 22:58:57 +0200 Subject: [PATCH 026/435] smoke: update mocha --- test/smoke/package.json | 2 +- test/smoke/yarn.lock | 475 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 439 insertions(+), 38 deletions(-) diff --git a/test/smoke/package.json b/test/smoke/package.json index be3067a8727..aedec3f8717 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -19,7 +19,7 @@ "cpx": "^1.5.0", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", - "mocha": "^5.2.0", + "mocha": "^6.1.4", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "ncp": "^2.0.0", diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 221596fc2cb..330b02367e8 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -62,6 +62,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" @@ -77,11 +82,23 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -103,6 +120,13 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -254,6 +278,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + chalk@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -265,6 +294,15 @@ chalk@0.5.1: strip-ansi "^0.3.0" supports-color "^0.2.0" +chalk@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -301,6 +339,15 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -314,10 +361,17 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= commander@2.6.0: version "2.6.0" @@ -400,12 +454,12 @@ date-fns@^1.23.0: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" integrity sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw== -debug@3.1.0, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== +debug@3.2.6, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: - ms "2.0.0" + ms "^2.1.1" debug@^2.2.0, debug@^2.3.3: version "2.6.9" @@ -414,12 +468,17 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: - ms "^2.1.1" + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" @@ -431,6 +490,13 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -506,16 +572,51 @@ duplexer@^0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0: +es-abstract@^1.5.1: + version "1.14.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" + integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.0.0" + string.prototype.trimright "^2.0.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + exec-sh@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" @@ -617,6 +718,20 @@ find-index@^0.1.1: resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" integrity sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ= +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -656,6 +771,11 @@ fsevents@^1.0.0: nan "^2.12.1" node-pre-gyp "^0.12.0" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -670,6 +790,11 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -697,7 +822,19 @@ glob2base@^0.0.12: dependencies: find-index "^0.1.1" -glob@7.1.2, glob@^7.0.5: +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.5: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== @@ -736,6 +873,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -772,10 +914,17 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== htmlparser2@^3.9.2: version "3.9.2" @@ -847,6 +996,16 @@ is-buffer@^1.1.5, is-buffer@~1.1.1: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -861,6 +1020,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -963,6 +1127,20 @@ is-primitive@^2.0.0: resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -973,6 +1151,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -985,6 +1168,14 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -1014,16 +1205,36 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash@^4.16.4: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + lodash@^4.5.1: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw== +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -1159,29 +1370,41 @@ mocha-multi-reporters@^1.1.7: debug "^3.1.0" lodash "^4.16.4" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== +mocha@^6.1.4: + version "6.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" + integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== dependencies: + ansi-colors "3.2.3" browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" + debug "3.2.6" diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.2" + find-up "3.0.0" + glob "7.1.3" growl "1.10.5" - he "1.1.1" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" minimatch "3.0.4" mkdirp "0.5.1" - supports-color "5.4.0" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.1, ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== @@ -1222,6 +1445,14 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-pre-gyp@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" @@ -1295,6 +1526,16 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -1302,6 +1543,24 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1342,6 +1601,25 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -1357,6 +1635,11 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1485,6 +1768,16 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -1546,7 +1839,12 @@ semver@^5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== -set-blocking@~2.0.0: +semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -1639,6 +1937,11 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -1664,6 +1967,31 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -1699,7 +2027,14 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -1711,10 +2046,10 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" @@ -1730,6 +2065,13 @@ supports-color@^3.2.3: dependencies: has-flag "^1.0.0" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + tar@^4: version "4.4.10" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" @@ -1826,13 +2168,34 @@ watch@^1.0.2: exec-sh "^0.2.0" minimist "^1.2.0" -wide-align@^1.1.0: +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -1843,7 +2206,45 @@ xml@^1.0.0: resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + yallist@^3.0.0, yallist@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" From 3ae6f0bf93b86401f145f6320023cd6e844858b2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 28 Sep 2019 09:12:17 -0700 Subject: [PATCH 027/435] Annotate that `preferredEncoding` can be undefined Discovered as part of #81574 --- .../services/textfile/common/textFileEditorModel.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 3181a91d1c1..900b4f6eed8 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -77,10 +77,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil private resource: URI; - private contentEncoding: string; // encoding as reported from disk - private preferredEncoding: string; // encoding as chosen by the user + private contentEncoding: string; // encoding as reported from disk + private preferredEncoding: string | undefined; // encoding as chosen by the user - private preferredMode: string | undefined; // mode as chosen by the user + private preferredMode: string | undefined; // mode as chosen by the user private versionId: number; private bufferSavedVersionId: number; @@ -107,7 +107,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil constructor( resource: URI, - preferredEncoding: string, + preferredEncoding: string | undefined, preferredMode: string | undefined, @INotificationService private readonly notificationService: INotificationService, @IModeService modeService: IModeService, From 8079ff0001894aa7299638274cd80204419581c7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 11:02:24 -0700 Subject: [PATCH 028/435] Rename resolveExternalUri to asExternalUri #81131 --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/browser/mainThreadWindow.ts | 2 +- src/vs/workbench/api/common/extHost.api.impl.ts | 4 ++-- src/vs/workbench/api/common/extHost.protocol.ts | 2 +- src/vs/workbench/api/common/extHostWindow.ts | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 0f113996abc..42f75de4c68 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1168,7 +1168,7 @@ declare module 'vscode' { * * @return A uri that can be used on the client machine. */ - export function resolveExternalUri(target: Uri): Thenable; + export function asExternalUri(target: Uri): Thenable; } //#endregion diff --git a/src/vs/workbench/api/browser/mainThreadWindow.ts b/src/vs/workbench/api/browser/mainThreadWindow.ts index ff2074055e4..bbce19a3388 100644 --- a/src/vs/workbench/api/browser/mainThreadWindow.ts +++ b/src/vs/workbench/api/browser/mainThreadWindow.ts @@ -47,7 +47,7 @@ export class MainThreadWindow implements MainThreadWindowShape { return this.openerService.open(uri, { openExternal: true, allowTunneling: options.allowTunneling }); } - async $resolveExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise { + async $asExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise { const uri = URI.revive(uriComponents); const result = await this.openerService.resolveExternalUri(uri, options); return result.resolved; diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 5a6567b8a79..230d09a2903 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -247,9 +247,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I openExternal(uri: URI) { return extHostWindow.openUri(uri, { allowTunneling: !!initData.remote.isRemote }); }, - resolveExternalUri(uri: URI) { + asExternalUri(uri: URI) { checkProposedApiEnabled(extension); - return extHostWindow.resolveExternalUri(uri, { allowTunneling: !!initData.remote.isRemote }); + return extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.isRemote }); }, get remoteName() { return getRemoteName(initData.remote.authority); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 10f4c36261d..7bd6aa6cb78 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -746,7 +746,7 @@ export interface IOpenUriOptions { export interface MainThreadWindowShape extends IDisposable { $getWindowVisibility(): Promise; $openUri(uri: UriComponents, options: IOpenUriOptions): Promise; - $resolveExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise; + $asExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise; } // -- extension host diff --git a/src/vs/workbench/api/common/extHostWindow.ts b/src/vs/workbench/api/common/extHostWindow.ts index 7017c29788e..8ce82ac8b2d 100644 --- a/src/vs/workbench/api/common/extHostWindow.ts +++ b/src/vs/workbench/api/common/extHostWindow.ts @@ -54,14 +54,14 @@ export class ExtHostWindow implements ExtHostWindowShape { return this._proxy.$openUri(stringOrUri, options); } - async resolveExternalUri(uri: URI, options: IOpenUriOptions): Promise { + async asExternalUri(uri: URI, options: IOpenUriOptions): Promise { if (isFalsyOrWhitespace(uri.scheme)) { return Promise.reject('Invalid scheme - cannot be empty'); } else if (!new Set([Schemas.http, Schemas.https]).has(uri.scheme)) { return Promise.reject(`Invalid scheme '${uri.scheme}'`); } - const result = await this._proxy.$resolveExternalUri(uri, options); + const result = await this._proxy.$asExternalUri(uri, options); return URI.from(result); } } From e904a5f646af4c5a667a12393351d47b806e885a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 14:22:38 -0700 Subject: [PATCH 029/435] Warn development webview extensions that use `vscode-resource` uris directly Fixes #81685 --- src/vs/workbench/api/common/extHostWebview.ts | 19 ++++++++++++++----- src/vs/workbench/api/common/shared/webview.ts | 1 + .../api/extHostWebview.test.ts | 12 +++++++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 9abd2df4d11..70395b6f301 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -7,7 +7,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { URI, UriComponents } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import * as modes from 'vs/editor/common/modes'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview'; @@ -20,6 +20,7 @@ type IconPath = URI | { light: URI, dark: URI }; export class ExtHostWebview implements vscode.Webview { private _html: string; private _isDisposed: boolean = false; + private _hasCalledAsWebviewUri = false; public readonly _onMessageEmitter = new Emitter(); public readonly onDidReceiveMessage: Event = this._onMessageEmitter.event; @@ -28,7 +29,8 @@ export class ExtHostWebview implements vscode.Webview { private readonly _handle: WebviewPanelHandle, private readonly _proxy: MainThreadWebviewsShape, private _options: vscode.WebviewOptions, - private readonly _initData: WebviewInitData + private readonly _initData: WebviewInitData, + private readonly _extensionId: ExtensionIdentifier | undefined, ) { } public dispose() { @@ -36,6 +38,7 @@ export class ExtHostWebview implements vscode.Webview { } public asWebviewUri(resource: vscode.Uri): vscode.Uri { + this._hasCalledAsWebviewUri = true; return asWebviewUri(this._initData, this._handle, resource); } @@ -53,6 +56,12 @@ export class ExtHostWebview implements vscode.Webview { this.assertNotDisposed(); if (this._html !== value) { this._html = value; + if (this._initData.isExtensionDevelopmentDebug && this._extensionId && !this._hasCalledAsWebviewUri) { + if (/(["'])vscode-resource:([^\s'"]+?)(["'])/i.test(value)) { + this._hasCalledAsWebviewUri = true; + console.warn(`${this._extensionId.value} created a webview that appears to use the vscode-resource scheme directly. Please migrate to use the 'webview.asWebviewUri' api instead: https://aka.ms/vscode-webview-use-aswebviewuri`); + } + } this._proxy.$setHtml(this._handle, value); } } @@ -290,7 +299,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { const handle = ExtHostWebviews.newHandle(); this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, convertWebviewOptions(options), extension.identifier, extension.extensionLocation); - const webview = new ExtHostWebview(handle, this._proxy, options, this.initData); + const webview = new ExtHostWebview(handle, this._proxy, options, this.initData, extension.identifier); const panel = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, viewColumn, options, webview); this._webviewPanels.set(handle, panel); return panel; @@ -405,7 +414,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { return Promise.reject(new Error(`No serializer found for '${viewType}'`)); } - const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData); + const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData, undefined); const revivedPanel = new ExtHostWebviewEditor(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview); this._webviewPanels.set(webviewHandle, revivedPanel); return Promise.resolve(serializer.deserializeWebviewPanel(revivedPanel, state)); @@ -432,7 +441,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { this._proxy.$setExtension(handle, extension.identifier, extension.extensionLocation); - const webview = new ExtHostWebview(handle, this._proxy, options, this.initData); + const webview = new ExtHostWebview(handle, this._proxy, options, this.initData, extension.identifier); const revivedPanel = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview); this._webviewPanels.set(handle, revivedPanel); return Promise.resolve(provider.resolveWebviewEditor(URI.revive(resource), revivedPanel)); diff --git a/src/vs/workbench/api/common/shared/webview.ts b/src/vs/workbench/api/common/shared/webview.ts index 6b44c25c76b..6d5a52928f8 100644 --- a/src/vs/workbench/api/common/shared/webview.ts +++ b/src/vs/workbench/api/common/shared/webview.ts @@ -7,6 +7,7 @@ import { URI } from 'vs/base/common/uri'; import * as vscode from 'vscode'; export interface WebviewInitData { + readonly isExtensionDevelopmentDebug: boolean; readonly webviewResourceRoot: string; readonly webviewCspSource: string; } diff --git a/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts index c161ca4c462..a2117d7652e 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts @@ -18,7 +18,11 @@ suite('ExtHostWebview', () => { const viewType = 'view.type'; const shape = createNoopMainThreadWebviews(); - const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape), { webviewCspSource: '', webviewResourceRoot: '' }); + const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape), { + webviewCspSource: '', + webviewResourceRoot: '', + isExtensionDevelopmentDebug: false, + }); let lastInvokedDeserializer: vscode.WebviewPanelSerializer | undefined = undefined; @@ -52,7 +56,8 @@ suite('ExtHostWebview', () => { const shape = createNoopMainThreadWebviews(); const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape), { webviewCspSource: '', - webviewResourceRoot: 'vscode-resource://{{resource}}' + webviewResourceRoot: 'vscode-resource://{{resource}}', + isExtensionDevelopmentDebug: false, }); const webview = extHostWebviews.createWebviewPanel({} as any, 'type', 'title', 1, {}); @@ -92,7 +97,8 @@ suite('ExtHostWebview', () => { const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape), { webviewCspSource: '', - webviewResourceRoot: `https://{{uuid}}.webview.contoso.com/commit/{{resource}}` + webviewResourceRoot: `https://{{uuid}}.webview.contoso.com/commit/{{resource}}`, + isExtensionDevelopmentDebug: false, }); const webview = extHostWebviews.createWebviewPanel({} as any, 'type', 'title', 1, {}); From df0953c04584c59946d5edea977aae60623a605d Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 30 Sep 2019 14:41:45 -0700 Subject: [PATCH 030/435] Fix setting row colors Remove focus outline on settings editor. It's not tabbable so it doesn't serve any purpose and is annoying to see every time I click on the editor background. Just need to keep .editor-instance from getting focus on click. Fix #81675 --- .../browser/media/settingsEditor2.css | 4 ++++ .../preferences/browser/settingsEditor2.ts | 2 +- .../preferences/browser/settingsTree.ts | 20 +++++++++---------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css index b0dff5ac885..200c92379d8 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css @@ -16,6 +16,10 @@ color: inherit !important; } +.settings-editor:focus { + outline: none !important; +} + /* header styling */ .settings-editor > .settings-header { box-sizing: border-box; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 7e3bca1e76f..e837a8221b0 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -201,7 +201,7 @@ export class SettingsEditor2 extends BaseEditor { createEditor(parent: HTMLElement): void { parent.setAttribute('tabindex', '-1'); - this.rootElement = DOM.append(parent, $('.settings-editor')); + this.rootElement = DOM.append(parent, $('.settings-editor', { tabindex: '-1' })); this.createHeader(this.rootElement); this.createBody(this.rootElement); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 4931271523c..1d2ec90a51a 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -37,7 +37,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; +import { errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, transparent } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler'; import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ITOCEntry } from 'vs/workbench/contrib/preferences/browser/settingsLayout'; @@ -1544,20 +1544,20 @@ export class SettingsTree extends ObjectTree { this.getHTMLElement().classList.add(treeClass); this.disposables.push(attachStyler(themeService, { - listActiveSelectionBackground: 'transparent', + listActiveSelectionBackground: transparent(Color.white, 0), listActiveSelectionForeground: foreground, - listFocusAndSelectionBackground: 'transparent', + listFocusAndSelectionBackground: transparent(Color.white, 0), listFocusAndSelectionForeground: foreground, - listFocusBackground: 'transparent', + listFocusBackground: transparent(Color.white, 0), listFocusForeground: foreground, listHoverForeground: foreground, - listHoverBackground: 'transparent', - listHoverOutline: 'transparent', - listFocusOutline: 'transparent', - listInactiveSelectionBackground: 'transparent', + listHoverBackground: transparent(Color.white, 0), + listHoverOutline: transparent(Color.white, 0), + listFocusOutline: transparent(Color.white, 0), + listInactiveSelectionBackground: transparent(Color.white, 0), listInactiveSelectionForeground: foreground, - listInactiveFocusBackground: 'transparent', - listInactiveFocusOutline: 'transparent' + listInactiveFocusBackground: transparent(Color.white, 0), + listInactiveFocusOutline: transparent(Color.white, 0) }, colors => { this.style(colors); })); From 48e1250e2f2d2d0def3c501756482bf9762abe62 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 30 Sep 2019 15:09:49 -0700 Subject: [PATCH 031/435] Fix #81690 --- .../contrib/preferences/browser/settingsTree.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 1d2ec90a51a..6962f9d1ded 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -394,15 +394,12 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre }); toolbar.setActions([], this.settingActions)(); - // change icon from ellipsis to gear - let icon = container.querySelector('.codicon-more'); - if (icon) { - (icon).classList.add('codicon-gear'); - } - - const button = container.querySelector('.toolbar-toggle-more'); + const button = container.querySelector('.codicon-more'); if (button) { (button).tabIndex = -1; + + // change icon from ellipsis to gear + (button).classList.add('codicon-gear'); } return toolbar; From f832acfbd96a254b1b4d9218bb679114c33c3052 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 30 Sep 2019 15:15:49 -0700 Subject: [PATCH 032/435] Settings editor fixes - Fix keyboard shortcut to show context menu - Fix showing gear icon when settings row is focused --- .../contrib/preferences/browser/media/settingsEditor2.css | 2 +- src/vs/workbench/contrib/preferences/browser/settingsTree.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css index 200c92379d8..276965c3f63 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css @@ -162,7 +162,7 @@ } .settings-editor > .settings-body .settings-tree-container .monaco-list-row .mouseover .setting-toolbar-container > .monaco-toolbar .codicon-more, -.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-item.focused .setting-toolbar-container > .monaco-toolbar .codicon-more, +.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-item-contents.focused .setting-toolbar-container > .monaco-toolbar .codicon-more, .settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-toolbar-container:hover > .monaco-toolbar .codicon-more, .settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-toolbar-container > .monaco-toolbar .active .codicon-more { opacity: 1; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 6962f9d1ded..8f9829317ff 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -413,7 +413,6 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre const setting = element.setting; DOM.toggleClass(template.containerElement, 'is-configured', element.isConfigured); - DOM.toggleClass(template.containerElement, 'is-expanded', true); template.containerElement.setAttribute(AbstractSettingRenderer.SETTING_KEY_ATTR, element.setting.key); template.containerElement.setAttribute(AbstractSettingRenderer.SETTING_ID_ATTR, element.id); @@ -1216,7 +1215,7 @@ export class SettingTreeRenderers { } showContextMenu(element: SettingsTreeSettingElement, settingDOMElement: HTMLElement): void { - const toolbarElement = settingDOMElement.querySelector('.toolbar-toggle-more'); + const toolbarElement = settingDOMElement.querySelector('.monaco-toolbar'); if (toolbarElement) { this._contextMenuService.showContextMenu({ getActions: () => this.settingActions, From 1c215ef3f65b6f2aad22d76337a92348b0aaf17f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 16:03:03 -0700 Subject: [PATCH 033/435] Try different name for default editor Fixes #80777 --- src/vs/workbench/contrib/customEditor/browser/customEditors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index a38b00bab20..852e62956cd 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -33,7 +33,7 @@ const defaultEditorId = 'default'; const defaultEditorInfo: CustomEditorInfo = { id: defaultEditorId, - displayName: nls.localize('promptOpenWith.defaultEditor', "Default built-in editor"), + displayName: nls.localize('promptOpenWith.defaultEditor', "VS Code's standard text editor"), selector: [ { filenamePattern: '*' } ], From 9cba8ad16de909eb8e61d8d06d4043b9e0fcc30c Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Mon, 30 Sep 2019 16:02:59 -0700 Subject: [PATCH 034/435] fixes #81267 --- src/vs/base/browser/ui/menu/menu.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 131023cadad..41ccd8fffc2 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -398,7 +398,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem { EventHelper.stop(e, true); this.onClick(e); })); - }, 50); + }, 100); this._register(this.runOnceToEnableMouseUp); } From 2aea209a3eacc7cf9768f1530ce9eb23a79833a1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 16:09:59 -0700 Subject: [PATCH 035/435] Add fallback for invalid signature help data structure Fixes #80617 Some extensions may provide us with bad data types (if they are js or don't have strict null enabled for example). Try to be more careful about handling such cases by falling back to an empty array instead of undefined --- src/vs/workbench/api/common/extHostTypeConverters.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index cecf59ef4f1..48da096d566 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -859,7 +859,7 @@ export namespace SignatureInformation { return { label: info.label, documentation: info.documentation ? MarkdownString.fromStrict(info.documentation) : undefined, - parameters: info.parameters && info.parameters.map(ParameterInformation.from) + parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.from) : [] }; } @@ -867,7 +867,7 @@ export namespace SignatureInformation { return { label: info.label, documentation: htmlContent.isMarkdownString(info.documentation) ? MarkdownString.to(info.documentation) : info.documentation, - parameters: info.parameters && info.parameters.map(ParameterInformation.to) + parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.to) : [] }; } } @@ -878,7 +878,7 @@ export namespace SignatureHelp { return { activeSignature: help.activeSignature, activeParameter: help.activeParameter, - signatures: help.signatures && help.signatures.map(SignatureInformation.from) + signatures: Array.isArray(help.signatures) ? help.signatures.map(SignatureInformation.from) : [], }; } @@ -886,7 +886,7 @@ export namespace SignatureHelp { return { activeSignature: help.activeSignature, activeParameter: help.activeParameter, - signatures: help.signatures && help.signatures.map(SignatureInformation.to) + signatures: Array.isArray(help.signatures) ? help.signatures.map(SignatureInformation.to) : [], }; } } From fe0f0cc501e2c55a1dba3bd9b292da45d0b16564 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Mon, 30 Sep 2019 16:38:57 -0700 Subject: [PATCH 036/435] Fix monospace font-family not showing in deeper hover/suggest --- src/vs/editor/contrib/hover/hover.css | 2 +- src/vs/editor/contrib/suggest/media/suggest.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/hover/hover.css b/src/vs/editor/contrib/hover/hover.css index 8190705b9a5..49a1a6b0f4f 100644 --- a/src/vs/editor/contrib/hover/hover.css +++ b/src/vs/editor/contrib/hover/hover.css @@ -37,7 +37,7 @@ margin: 8px 0; } -.monaco-editor-hover p > code { +.monaco-editor-hover code { font-family: var(--monaco-monospace-font); } diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index b5b5519fe9c..197145ad27d 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -53,7 +53,7 @@ padding-left: 20px; } -.monaco-editor .suggest-widget > .details p > code { +.monaco-editor .suggest-widget > .details p code { font-family: var(--monaco-monospace-font); } From 9bb24dc1c1d24075541d58c7e32d09076512c305 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Mon, 30 Sep 2019 16:42:01 -0700 Subject: [PATCH 037/435] Upgrade html/css language services --- .../css-language-features/server/package.json | 2 +- .../css-language-features/server/yarn.lock | 8 ++++---- .../html-language-features/server/package.json | 4 ++-- .../html-language-features/server/yarn.lock | 16 ++++++++-------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 0616cb6f278..3d840a8346e 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,7 +9,7 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.9", + "vscode-css-languageservice": "^4.0.3-next.10", "vscode-languageserver": "^6.0.0-next.1" }, "devDependencies": { diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 08d99b91e27..66d2c02ad80 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -781,10 +781,10 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.9: - version "4.0.3-next.9" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.9.tgz#27e36bca98dc51cb99d4046fb84c99e00e629b2f" - integrity sha512-b1WQ+4/wFbgFTsmFyIQ8PjgD9M5dJBaBN67kAFMbyaavv7uemR2wuD6SiX1OsitmlVi3WEUtJZdLtka45r8dEw== +vscode-css-languageservice@^4.0.3-next.10: + version "4.0.3-next.10" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.10.tgz#e282e49303cdda267c2e72dc00d8c5fa1db4ec3c" + integrity sha512-dJFx71TzA5wfl46jrtbLR/Hm42CsuRJbeVlgEMcf2DcDtq7caw5iWGK7Ch4clALmjIyWPPXFWOyEo9kzZl26pw== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index fe5ae39087e..a51fb648fd7 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,8 +9,8 @@ }, "main": "./out/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.9", - "vscode-html-languageservice": "^3.0.4-next.4", + "vscode-css-languageservice": "^4.0.3-next.10", + "vscode-html-languageservice": "^3.0.4-next.5", "vscode-languageserver": "^6.0.0-next.1", "vscode-languageserver-types": "3.15.0-next.5", "vscode-nls": "^4.1.1", diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index ad45194dff7..db7cefb3430 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -611,19 +611,19 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.9: - version "4.0.3-next.9" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.9.tgz#27e36bca98dc51cb99d4046fb84c99e00e629b2f" - integrity sha512-b1WQ+4/wFbgFTsmFyIQ8PjgD9M5dJBaBN67kAFMbyaavv7uemR2wuD6SiX1OsitmlVi3WEUtJZdLtka45r8dEw== +vscode-css-languageservice@^4.0.3-next.10: + version "4.0.3-next.10" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.10.tgz#e282e49303cdda267c2e72dc00d8c5fa1db4ec3c" + integrity sha512-dJFx71TzA5wfl46jrtbLR/Hm42CsuRJbeVlgEMcf2DcDtq7caw5iWGK7Ch4clALmjIyWPPXFWOyEo9kzZl26pw== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-html-languageservice@^3.0.4-next.4: - version "3.0.4-next.4" - resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.4.tgz#e7cfd9429feb6e212606dee6de49f54b9f1449da" - integrity sha512-r8FgQIunfA6gq7LxJ7/iD8O6JHgpQeEhy8IfTiQNlKSsWcSBXubn4hdUgjHYWo+On2CW9ZIQLdle/9Xg4xh3aw== +vscode-html-languageservice@^3.0.4-next.5: + version "3.0.4-next.5" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.5.tgz#cf8bbb8deb80b06d43f41f485e0e6fdcaf6655ca" + integrity sha512-cEjWRRqO49nVIcaGkLrA4FY1CMPzIAFiK8QLY2hY/8lTX9ZxvGhuegY6MBQqyvLJyZPpWJ2yP9iWlMEPeX655A== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" From 71c95a466f3f9cc3c6519109a3123ad3f8caf188 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 20:14:12 -0700 Subject: [PATCH 038/435] Disable open with command for now It needs more polishing and should probably only be enabled for files that may have custom editors enabled --- .../contrib/customEditor/browser/commands.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/commands.ts b/src/vs/workbench/contrib/customEditor/browser/commands.ts index 9137385cc80..44ff3ec8490 100644 --- a/src/vs/workbench/contrib/customEditor/browser/commands.ts +++ b/src/vs/workbench/contrib/customEditor/browser/commands.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schemas } from 'vs/base/common/network'; +// import { Schemas } from 'vs/base/common/network'; +import { firstOrDefault } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import * as nls from 'vs/nls'; @@ -12,19 +13,18 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IListService } from 'vs/platform/list/browser/listService'; import { IEditorCommandsContext } from 'vs/workbench/common/editor'; -import { ResourceContextKey } from 'vs/workbench/common/resources'; +// import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { firstOrDefault } from 'vs/base/common/arrays'; const viewCategory = nls.localize('viewCategory', "View"); // #region Open With const OPEN_WITH_COMMAND_ID = 'openWith'; -const OPEN_WITH_TITLE = { value: nls.localize('openWith.title', 'Open With'), original: 'Open With' }; +// const OPEN_WITH_TITLE = { value: nls.localize('openWith.title', 'Open With'), original: 'Open With' }; KeybindingsRegistry.registerCommandAndKeybindingRule({ id: OPEN_WITH_COMMAND_ID, @@ -41,15 +41,15 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { - group: 'navigation', - order: 20, - command: { - id: OPEN_WITH_COMMAND_ID, - title: OPEN_WITH_TITLE, - }, - when: ResourceContextKey.Scheme.isEqualTo(Schemas.file) -}); +// MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { +// group: 'navigation', +// order: 20, +// command: { +// id: OPEN_WITH_COMMAND_ID, +// title: OPEN_WITH_TITLE, +// }, +// when: ResourceContextKey.Scheme.isEqualTo(Schemas.file) +// }); // #endregion From f75285a4e1eeb8726a5d1382e93e585fd6864bd0 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 20:15:26 -0700 Subject: [PATCH 039/435] Remove `save` / `state` from custom editor api proposal for now These features are not working in many cases and the api around them will likely change significantly --- src/vs/vscode.proposed.d.ts | 38 ------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 42f75de4c68..aa09f54131f 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1085,45 +1085,7 @@ declare module 'vscode' { //#region Custom editors, mjbvz - export enum WebviewContentState { - /** - * The webview content cannot be modified. - * - * This disables save. - */ - Readonly = 1, - - /** - * The webview content has not been changed but they can be modified and saved. - */ - Unchanged = 2, - - /** - * The webview content has been changed and can be saved. - */ - Dirty = 3, - } - - export interface WebviewEditorState { - readonly contentState: WebviewContentState; - } - - export interface WebviewPanel { - editorState: WebviewEditorState; - - /** - * Fired when the webview is being saved. - * - * Both `Unchanged` and `Dirty` editors can be saved. - * - * Extensions should call `waitUntil` to signal when the save operation complete - */ - readonly onWillSave: Event<{ waitUntil: (thenable: Thenable) => void }>; - } - export interface WebviewEditor extends WebviewPanel { - // TODO: We likely do not want `editorState` and `onWillSave` enabled for - // resource backed webviews } export interface WebviewEditorProvider { From 313ede61cbad8f9dc748907b3384e059ddddb79a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Sep 2019 20:36:21 -0700 Subject: [PATCH 040/435] Also remove extHostWebview side of the api proposal for webview editor state/save --- .../workbench/api/common/extHostTypeConverters.ts | 10 ---------- src/vs/workbench/api/common/extHostWebview.ts | 14 +------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 48da096d566..dfce55ade92 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1163,13 +1163,3 @@ export namespace LogLevel { return types.LogLevel.Info; } } -export namespace WebviewContentState { - export function from(state: vscode.WebviewContentState): modes.WebviewContentState { - switch (state) { - case types.WebviewContentState.Readonly: return modes.WebviewContentState.Readonly; - case types.WebviewContentState.Unchanged: return modes.WebviewContentState.Unchanged; - case types.WebviewContentState.Dirty: return modes.WebviewContentState.Dirty; - default: throw new Error('Unknown vscode.WebviewContentState'); - } - } -} diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 70395b6f301..763f79dc5f6 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -13,7 +13,7 @@ import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview'; import * as vscode from 'vscode'; import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol'; -import { Disposable, WebviewContentState } from './extHostTypes'; +import { Disposable } from './extHostTypes'; type IconPath = URI | { light: URI, dark: URI }; @@ -102,9 +102,6 @@ export class ExtHostWebviewEditor implements vscode.WebviewEditor { private _viewColumn: vscode.ViewColumn | undefined; private _visible: boolean = true; private _active: boolean = true; - private _state: vscode.WebviewEditorState = { - contentState: WebviewContentState.Readonly, - }; _isDisposed: boolean = false; @@ -224,15 +221,6 @@ export class ExtHostWebviewEditor implements vscode.WebviewEditor { this._visible = value; } - public get editorState(): vscode.WebviewEditorState { - return this._state; - } - - public set editorState(newState: vscode.WebviewEditorState) { - this._state = newState; - this._proxy.$setState(this._handle, typeConverters.WebviewContentState.from(newState.contentState)); - } - private readonly _onWillSave = new Emitter<{ waitUntil: (thenable: Thenable) => void }>(); public readonly onWillSave = this._onWillSave.event; From 2724ca6c053585673ee9cb26527d18657a51dfa9 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 1 Oct 2019 09:49:17 +0200 Subject: [PATCH 041/435] styler: allow Color --- src/vs/platform/theme/common/colorRegistry.ts | 2 +- src/vs/platform/theme/common/styler.ts | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index e73b91f4277..2bfcd5cfd05 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -473,7 +473,7 @@ function lessProminent(colorValue: ColorValue, backgroundColorValue: ColorValue, /** * @param colorValue Resolve a color value in the context of a theme */ -function resolveColorValue(colorValue: ColorValue | null, theme: ITheme): Color | undefined { +export function resolveColorValue(colorValue: ColorValue | null, theme: ITheme): Color | undefined { if (colorValue === null) { return undefined; } else if (typeof colorValue === 'string') { diff --git a/src/vs/platform/theme/common/styler.ts b/src/vs/platform/theme/common/styler.ts index 8ce034bd94c..56f0deef229 100644 --- a/src/vs/platform/theme/common/styler.ts +++ b/src/vs/platform/theme/common/styler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, inputActiveOptionBackground, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, badgeBackground, badgeForeground, progressBarBackground, breadcrumbsForeground, breadcrumbsFocusForeground, breadcrumbsActiveSelectionForeground, breadcrumbsBackground, editorWidgetBorder, inputValidationInfoForeground, inputValidationWarningForeground, inputValidationErrorForeground, menuForeground, menuBackground, menuSelectionForeground, menuSelectionBackground, menuSelectionBorder, menuBorder, menuSeparatorBackground, darken, listFilterWidgetOutline, listFilterWidgetNoMatchesOutline, listFilterWidgetBackground, editorWidgetBackground, treeIndentGuidesStroke, editorWidgetForeground, simpleCheckboxBackground, simpleCheckboxBorder, simpleCheckboxForeground } from 'vs/platform/theme/common/colorRegistry'; +import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, inputActiveOptionBackground, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, badgeBackground, badgeForeground, progressBarBackground, breadcrumbsForeground, breadcrumbsFocusForeground, breadcrumbsActiveSelectionForeground, breadcrumbsBackground, editorWidgetBorder, inputValidationInfoForeground, inputValidationWarningForeground, inputValidationErrorForeground, menuForeground, menuBackground, menuSelectionForeground, menuSelectionBackground, menuSelectionBorder, menuBorder, menuSeparatorBackground, darken, listFilterWidgetOutline, listFilterWidgetNoMatchesOutline, listFilterWidgetBackground, editorWidgetBackground, treeIndentGuidesStroke, editorWidgetForeground, simpleCheckboxBackground, simpleCheckboxBorder, simpleCheckboxForeground, ColorValue, resolveColorValue } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; @@ -20,7 +20,7 @@ export interface IThemable { } export interface IColorMapping { - [optionsKey: string]: ColorIdentifier | ColorFunction | undefined; + [optionsKey: string]: ColorValue | undefined; } export interface IComputedStyles { @@ -30,11 +30,9 @@ export interface IComputedStyles { export function computeStyles(theme: ITheme, styleMap: IColorMapping): IComputedStyles { const styles = Object.create(null) as IComputedStyles; for (let key in styleMap) { - const value = styleMap[key as string]; - if (typeof value === 'string') { - styles[key] = theme.getColor(value); - } else if (typeof value === 'function') { - styles[key] = value(theme); + const value = styleMap[key]; + if (value) { + styles[key] = resolveColorValue(value, theme); } } From 20876ae53b2fbfbfb4501dfe4cf78fdd0cbfd5ff Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Oct 2019 12:10:38 +0200 Subject: [PATCH 042/435] telemetry - fix broken opt out --- src/vs/workbench/common/contributions.ts | 2 +- .../gettingStarted/browser/telemetryOptOut.ts | 86 +++++++++++-------- .../electron-browser/telemetryOptOut.ts | 2 + 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/vs/workbench/common/contributions.ts b/src/vs/workbench/common/contributions.ts index e1bc5735a3a..0d89c00ae0e 100644 --- a/src/vs/workbench/common/contributions.ts +++ b/src/vs/workbench/common/contributions.ts @@ -119,7 +119,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry try { instantiationService.createInstance(ctor); } catch (error) { - console.error(`Unable to instantiate workbench contribution ${ctor}.`, error); + console.error(`Unable to instantiate workbench contribution ${(ctor as any).name}.`, error); } } } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts index 2d4448c5099..b60f680e467 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts @@ -10,7 +10,6 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { onUnexpectedError } from 'vs/base/common/errors'; import { IExperimentService, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { language, locale } from 'vs/base/common/platform'; @@ -25,53 +24,56 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution private privacyUrl: string | undefined; constructor( - @IStorageService storageService: IStorageService, - @IOpenerService openerService: IOpenerService, + @IStorageService private readonly storageService: IStorageService, + @IOpenerService private readonly openerService: IOpenerService, @INotificationService private readonly notificationService: INotificationService, - @IHostService hostService: IHostService, + @IHostService private readonly hostService: IHostService, @ITelemetryService private readonly telemetryService: ITelemetryService, @IExperimentService private readonly experimentService: IExperimentService, @IConfigurationService private readonly configurationService: IConfigurationService, @IExtensionGalleryService private readonly galleryService: IExtensionGalleryService, - @IProductService productService: IProductService - ) { - if (!productService.telemetryOptOutUrl || storageService.get(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, StorageScope.GLOBAL)) { - return; - } - const experimentId = 'telemetryOptOut'; - Promise.all([ - this.getWindowCount(), - experimentService.getExperimentById(experimentId) - ]).then(([count, experimentState]) => { - if (!hostService.hasFocus && count > 1) { - return; + @IProductService private readonly productService: IProductService, + ) { } + + protected async handleTelemetryOptOut(): Promise { + if (this.productService.telemetryOptOutUrl && !this.storageService.get(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, StorageScope.GLOBAL)) { + const experimentId = 'telemetryOptOut'; + + const [count, experimentState] = await Promise.all([this.getWindowCount(), this.experimentService.getExperimentById(experimentId)]); + + if (!this.hostService.hasFocus && count > 1) { + return; // return early if meanwhile another window opened (we only show the opt-out once) } - storageService.store(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL); - this.privacyUrl = productService.privacyStatementUrl || productService.telemetryOptOutUrl; + this.storageService.store(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL); - if (experimentState && experimentState.state === ExperimentState.Run && telemetryService.isOptedIn) { + this.privacyUrl = this.productService.privacyStatementUrl || this.productService.telemetryOptOutUrl; + + if (experimentState && experimentState.state === ExperimentState.Run && this.telemetryService.isOptedIn) { this.runExperiment(experimentId); return; } - const telemetryOptOutUrl = productService.telemetryOptOutUrl; + const telemetryOptOutUrl = this.productService.telemetryOptOutUrl; if (telemetryOptOutUrl) { - const optOutNotice = localize('telemetryOptOut.optOutNotice', "Help improve VS Code by allowing Microsoft to collect usage data. Read our [privacy statement]({0}) and learn how to [opt out]({1}).", this.privacyUrl, productService.telemetryOptOutUrl); - const optInNotice = localize('telemetryOptOut.optInNotice', "Help improve VS Code by allowing Microsoft to collect usage data. Read our [privacy statement]({0}) and learn how to [opt in]({1}).", this.privacyUrl, productService.telemetryOptOutUrl); - - notificationService.prompt( - Severity.Info, - telemetryService.isOptedIn ? optOutNotice : optInNotice, - [{ - label: localize('telemetryOptOut.readMore', "Read More"), - run: () => openerService.open(URI.parse(telemetryOptOutUrl)) - }], - { sticky: true } - ); + this.showTelemetryOptOut(telemetryOptOutUrl); } - }) - .then(undefined, onUnexpectedError); + } + } + + private showTelemetryOptOut(telemetryOptOutUrl: string): void { + const optOutNotice = localize('telemetryOptOut.optOutNotice', "Help improve VS Code by allowing Microsoft to collect usage data. Read our [privacy statement]({0}) and learn how to [opt out]({1}).", this.privacyUrl, this.productService.telemetryOptOutUrl); + const optInNotice = localize('telemetryOptOut.optInNotice', "Help improve VS Code by allowing Microsoft to collect usage data. Read our [privacy statement]({0}) and learn how to [opt in]({1}).", this.privacyUrl, this.productService.telemetryOptOutUrl); + + this.notificationService.prompt( + Severity.Info, + this.telemetryService.isOptedIn ? optOutNotice : optInNotice, + [{ + label: localize('telemetryOptOut.readMore', "Read More"), + run: () => this.openerService.open(URI.parse(telemetryOptOutUrl)) + }], + { sticky: true } + ); } protected abstract getWindowCount(): Promise; @@ -153,6 +155,22 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution export class BrowserTelemetryOptOut extends AbstractTelemetryOptOut { + constructor( + @IStorageService storageService: IStorageService, + @IOpenerService openerService: IOpenerService, + @INotificationService notificationService: INotificationService, + @IHostService hostService: IHostService, + @ITelemetryService telemetryService: ITelemetryService, + @IExperimentService experimentService: IExperimentService, + @IConfigurationService configurationService: IConfigurationService, + @IExtensionGalleryService galleryService: IExtensionGalleryService, + @IProductService productService: IProductService + ) { + super(storageService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService); + + this.handleTelemetryOptOut(); + } + protected async getWindowCount(): Promise { return 1; } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts index 7c6cb2bfb6e..ae045c341a3 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts @@ -30,6 +30,8 @@ export class NativeTelemetryOptOut extends AbstractTelemetryOptOut { @IElectronService private readonly electronService: IElectronService ) { super(storageService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService); + + this.handleTelemetryOptOut(); } protected getWindowCount(): Promise { From 62b2b7098d5096a940c6a8f4f9c136072fae9407 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 1 Oct 2019 15:33:27 +0200 Subject: [PATCH 043/435] Update jsdoc for TreeView title Fixes https://github.com/microsoft/vscode/issues/81712 and https://github.com/microsoft/vscode/issues/81736 --- src/vs/vscode.proposed.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index aa09f54131f..a606623a3a1 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -871,7 +871,8 @@ declare module 'vscode' { export interface TreeView { /** - * The name of the tree view. It is set from the extension package.json and can be changed later. + * The tree view title is initially taken from the extension package.json + * Changes to the title property will be properly reflected in the UI in the title of the view. */ title?: string; } From 85cfc55a697064e36040a7fb75ef97e0d264d529 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Tue, 1 Oct 2019 08:02:41 -0700 Subject: [PATCH 044/435] Tweak wording of minimap.selectionHighlight description, fixes #81730 --- src/vs/platform/theme/common/colorRegistry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index 2bfcd5cfd05..aae4462b6fc 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -404,7 +404,7 @@ export const overviewRulerFindMatchForeground = registerColor('editorOverviewRul export const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.'), true); export const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hc: '#AB5A00' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true); -export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#f3f518' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the current editor selection.'), true); +export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#f3f518' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the editor selection.'), true); // ----- color functions From 2966f6f05d6f98b8400a5ff374bd4ccae3eecea1 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 1 Oct 2019 18:12:40 +0200 Subject: [PATCH 045/435] update distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d4deb1c047d..4feda2c221a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "afbdc1c13e8f8c6eb97a392e1e98bd9474d4bfef", + "distro": "dc014344371646422438f73f01ea6709c5ad19e7", "author": { "name": "Microsoft Corporation" }, @@ -153,4 +153,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From e520a1bcef8e9110cd366fbb10d4d1e900f9088e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 1 Oct 2019 18:13:53 +0200 Subject: [PATCH 046/435] make sure all, not some, decorations are unused before removing its css rule, #81467 --- .../services/decorations/browser/decorationsService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 0d63a904f6c..cde13b00f2c 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -172,7 +172,7 @@ class DecorationStyles extends Disposable { if (value.isUnused()) { let remove: boolean = false; if (Array.isArray(data)) { - remove = data.some(data => !usedDecorations.has(DecorationRule.keyOf(data))); + remove = data.every(data => !usedDecorations.has(DecorationRule.keyOf(data))); } else if (!usedDecorations.has(DecorationRule.keyOf(data))) { remove = true; } From 9c1fa6f48e19e6424fe082e870317de10dbf6b38 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 1 Oct 2019 18:33:49 +0200 Subject: [PATCH 047/435] Fixes #81762 --- src/vs/base/browser/mouseEvent.ts | 63 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/vs/base/browser/mouseEvent.ts b/src/vs/base/browser/mouseEvent.ts index ce270d0dda1..f3f2089100b 100644 --- a/src/vs/base/browser/mouseEvent.ts +++ b/src/vs/base/browser/mouseEvent.ts @@ -152,8 +152,16 @@ export class StandardWheelEvent { this.deltaX = deltaX; if (e) { - if (e.type === 'wheel') { + // Old (deprecated) wheel events + let e1 = e; + let e2 = e; + // vertical delta scroll + if (typeof e1.wheelDeltaY !== 'undefined') { + this.deltaY = e1.wheelDeltaY / 120; + } else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) { + this.deltaY = -e2.detail / 3; + } else if (e.type === 'wheel') { // Modern wheel event // https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent const ev = e; @@ -161,39 +169,36 @@ export class StandardWheelEvent { if (ev.deltaMode === ev.DOM_DELTA_LINE) { // the deltas are expressed in lines this.deltaY = -e.deltaY; - this.deltaX = -e.deltaX; } else { this.deltaY = -e.deltaY / 40; + } + } + + // horizontal delta scroll + if (typeof e1.wheelDeltaX !== 'undefined') { + if (browser.isSafari && platform.isWindows) { + this.deltaX = - (e1.wheelDeltaX / 120); + } else { + this.deltaX = e1.wheelDeltaX / 120; + } + } else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) { + this.deltaX = -e.detail / 3; + } else if (e.type === 'wheel') { + // Modern wheel event + // https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent + const ev = e; + + if (ev.deltaMode === ev.DOM_DELTA_LINE) { + // the deltas are expressed in lines + this.deltaX = -e.deltaX; + } else { this.deltaX = -e.deltaX / 40; } + } - } else { - // Old (deprecated) wheel events - let e1 = e; - let e2 = e; - - // vertical delta scroll - if (typeof e1.wheelDeltaY !== 'undefined') { - this.deltaY = e1.wheelDeltaY / 120; - } else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) { - this.deltaY = -e2.detail / 3; - } - - // horizontal delta scroll - if (typeof e1.wheelDeltaX !== 'undefined') { - if (browser.isSafari && platform.isWindows) { - this.deltaX = - (e1.wheelDeltaX / 120); - } else { - this.deltaX = e1.wheelDeltaX / 120; - } - } else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) { - this.deltaX = -e.detail / 3; - } - - // Assume a vertical scroll if nothing else worked - if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) { - this.deltaY = e.wheelDelta / 120; - } + // Assume a vertical scroll if nothing else worked + if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) { + this.deltaY = e.wheelDelta / 120; } } } From a3fc301dc4e37459daca8fcc1f3ae71b64877811 Mon Sep 17 00:00:00 2001 From: skprabhanjan Date: Tue, 1 Oct 2019 22:51:24 +0530 Subject: [PATCH 048/435] Changed hyphen and underscore ordering --- src/vs/base/common/search.ts | 17 +++++++------ .../contrib/find/test/replacePattern.test.ts | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/vs/base/common/search.ts b/src/vs/base/common/search.ts index d92882578b7..7b57f1e5a66 100644 --- a/src/vs/base/common/search.ts +++ b/src/vs/base/common/search.ts @@ -7,20 +7,19 @@ import * as strings from './strings'; export function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string { if (matches && (matches[0] !== '')) { + const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); + const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); + if (containsHyphens && !containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); + } else if (!containsHyphens && containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); + } if (matches[0].toUpperCase() === matches[0]) { return pattern.toUpperCase(); } else if (matches[0].toLowerCase() === matches[0]) { return pattern.toLowerCase(); } else if (strings.containsUppercaseCharacter(matches[0][0])) { - const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); - const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); - if (containsHyphens && !containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); - } else if (!containsHyphens && containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); - } else { - return pattern[0].toUpperCase() + pattern.substr(1); - } + return pattern[0].toUpperCase() + pattern.substr(1); } else { // we don't understand its pattern yet. return pattern; diff --git a/src/vs/editor/contrib/find/test/replacePattern.test.ts b/src/vs/editor/contrib/find/test/replacePattern.test.ts index 3371aa02994..2ed4a5c3056 100644 --- a/src/vs/editor/contrib/find/test/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/replacePattern.test.ts @@ -183,6 +183,10 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar-newabc'), 'Newfoo-Newbar-Newabc'); actual = ['Foo-Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'Newfoo-newbar'); + actual = ['foo-Bar']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-Newbar'); + actual = ['foo-BAR']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-NEWBAR'); actual = ['Foo_Bar']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_Newbar'); @@ -192,6 +196,10 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_newbar'); actual = ['Foo_Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar-abc'), 'Newfoo_newbar-abc'); + actual = ['foo_Bar']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'newfoo_Newbar'); + actual = ['Foo_BAR']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_NEWBAR'); }); test('preserve case', () => { @@ -227,6 +235,14 @@ suite('Replace Pattern test', () => { actual = replacePattern.buildReplaceString(['Foo-Bar-abc'], true); assert.equal(actual, 'Newfoo-newbar'); + replacePattern = parseReplaceString('newfoo-newbar'); + actual = replacePattern.buildReplaceString(['foo-Bar'], true); + assert.equal(actual, 'newfoo-Newbar'); + + replacePattern = parseReplaceString('newfoo-newbar'); + actual = replacePattern.buildReplaceString(['foo-BAR'], true); + assert.equal(actual, 'newfoo-NEWBAR'); + replacePattern = parseReplaceString('newfoo_newbar'); actual = replacePattern.buildReplaceString(['Foo_Bar'], true); assert.equal(actual, 'Newfoo_Newbar'); @@ -242,5 +258,13 @@ suite('Replace Pattern test', () => { replacePattern = parseReplaceString('newfoo_newbar-abc'); actual = replacePattern.buildReplaceString(['Foo_Bar-abc'], true); assert.equal(actual, 'Newfoo_newbar-abc'); + + replacePattern = parseReplaceString('newfoo_newbar'); + actual = replacePattern.buildReplaceString(['foo_Bar'], true); + assert.equal(actual, 'newfoo_Newbar'); + + replacePattern = parseReplaceString('newfoo_newbar'); + actual = replacePattern.buildReplaceString(['foo_BAR'], true); + assert.equal(actual, 'newfoo_NEWBAR'); }); }); From 27d7141d280730ef0fc3be0e3915a50c12600dee Mon Sep 17 00:00:00 2001 From: skprabhanjan Date: Tue, 1 Oct 2019 22:53:24 +0530 Subject: [PATCH 049/435] Revert "Changed hyphen and underscore ordering" This reverts commit a3fc301dc4e37459daca8fcc1f3ae71b64877811. --- src/vs/base/common/search.ts | 17 ++++++------- .../contrib/find/test/replacePattern.test.ts | 24 ------------------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/src/vs/base/common/search.ts b/src/vs/base/common/search.ts index 7b57f1e5a66..d92882578b7 100644 --- a/src/vs/base/common/search.ts +++ b/src/vs/base/common/search.ts @@ -7,19 +7,20 @@ import * as strings from './strings'; export function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string { if (matches && (matches[0] !== '')) { - const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); - const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); - if (containsHyphens && !containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); - } else if (!containsHyphens && containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); - } if (matches[0].toUpperCase() === matches[0]) { return pattern.toUpperCase(); } else if (matches[0].toLowerCase() === matches[0]) { return pattern.toLowerCase(); } else if (strings.containsUppercaseCharacter(matches[0][0])) { - return pattern[0].toUpperCase() + pattern.substr(1); + const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); + const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); + if (containsHyphens && !containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); + } else if (!containsHyphens && containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); + } else { + return pattern[0].toUpperCase() + pattern.substr(1); + } } else { // we don't understand its pattern yet. return pattern; diff --git a/src/vs/editor/contrib/find/test/replacePattern.test.ts b/src/vs/editor/contrib/find/test/replacePattern.test.ts index 2ed4a5c3056..3371aa02994 100644 --- a/src/vs/editor/contrib/find/test/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/replacePattern.test.ts @@ -183,10 +183,6 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar-newabc'), 'Newfoo-Newbar-Newabc'); actual = ['Foo-Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'Newfoo-newbar'); - actual = ['foo-Bar']; - assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-Newbar'); - actual = ['foo-BAR']; - assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-NEWBAR'); actual = ['Foo_Bar']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_Newbar'); @@ -196,10 +192,6 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_newbar'); actual = ['Foo_Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar-abc'), 'Newfoo_newbar-abc'); - actual = ['foo_Bar']; - assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'newfoo_Newbar'); - actual = ['Foo_BAR']; - assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_NEWBAR'); }); test('preserve case', () => { @@ -235,14 +227,6 @@ suite('Replace Pattern test', () => { actual = replacePattern.buildReplaceString(['Foo-Bar-abc'], true); assert.equal(actual, 'Newfoo-newbar'); - replacePattern = parseReplaceString('newfoo-newbar'); - actual = replacePattern.buildReplaceString(['foo-Bar'], true); - assert.equal(actual, 'newfoo-Newbar'); - - replacePattern = parseReplaceString('newfoo-newbar'); - actual = replacePattern.buildReplaceString(['foo-BAR'], true); - assert.equal(actual, 'newfoo-NEWBAR'); - replacePattern = parseReplaceString('newfoo_newbar'); actual = replacePattern.buildReplaceString(['Foo_Bar'], true); assert.equal(actual, 'Newfoo_Newbar'); @@ -258,13 +242,5 @@ suite('Replace Pattern test', () => { replacePattern = parseReplaceString('newfoo_newbar-abc'); actual = replacePattern.buildReplaceString(['Foo_Bar-abc'], true); assert.equal(actual, 'Newfoo_newbar-abc'); - - replacePattern = parseReplaceString('newfoo_newbar'); - actual = replacePattern.buildReplaceString(['foo_Bar'], true); - assert.equal(actual, 'newfoo_Newbar'); - - replacePattern = parseReplaceString('newfoo_newbar'); - actual = replacePattern.buildReplaceString(['foo_BAR'], true); - assert.equal(actual, 'newfoo_NEWBAR'); }); }); From 011186efc79548cb4e69310fd8d10460e0e59b10 Mon Sep 17 00:00:00 2001 From: skprabhanjan Date: Tue, 1 Oct 2019 22:54:38 +0530 Subject: [PATCH 050/435] Changed hyphen and underscore ordering --- src/vs/base/common/search.ts | 17 +++++++------ .../contrib/find/test/replacePattern.test.ts | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/vs/base/common/search.ts b/src/vs/base/common/search.ts index d92882578b7..7b57f1e5a66 100644 --- a/src/vs/base/common/search.ts +++ b/src/vs/base/common/search.ts @@ -7,20 +7,19 @@ import * as strings from './strings'; export function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string { if (matches && (matches[0] !== '')) { + const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); + const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); + if (containsHyphens && !containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); + } else if (!containsHyphens && containsUnderscores) { + return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); + } if (matches[0].toUpperCase() === matches[0]) { return pattern.toUpperCase(); } else if (matches[0].toLowerCase() === matches[0]) { return pattern.toLowerCase(); } else if (strings.containsUppercaseCharacter(matches[0][0])) { - const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); - const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); - if (containsHyphens && !containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-'); - } else if (!containsHyphens && containsUnderscores) { - return buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_'); - } else { - return pattern[0].toUpperCase() + pattern.substr(1); - } + return pattern[0].toUpperCase() + pattern.substr(1); } else { // we don't understand its pattern yet. return pattern; diff --git a/src/vs/editor/contrib/find/test/replacePattern.test.ts b/src/vs/editor/contrib/find/test/replacePattern.test.ts index 3371aa02994..2ed4a5c3056 100644 --- a/src/vs/editor/contrib/find/test/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/replacePattern.test.ts @@ -183,6 +183,10 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar-newabc'), 'Newfoo-Newbar-Newabc'); actual = ['Foo-Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'Newfoo-newbar'); + actual = ['foo-Bar']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-Newbar'); + actual = ['foo-BAR']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo-newbar'), 'newfoo-NEWBAR'); actual = ['Foo_Bar']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_Newbar'); @@ -192,6 +196,10 @@ suite('Replace Pattern test', () => { assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_newbar'); actual = ['Foo_Bar-abc']; assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar-abc'), 'Newfoo_newbar-abc'); + actual = ['foo_Bar']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'newfoo_Newbar'); + actual = ['Foo_BAR']; + assert.equal(buildReplaceStringWithCasePreserved(actual, 'newfoo_newbar'), 'Newfoo_NEWBAR'); }); test('preserve case', () => { @@ -227,6 +235,14 @@ suite('Replace Pattern test', () => { actual = replacePattern.buildReplaceString(['Foo-Bar-abc'], true); assert.equal(actual, 'Newfoo-newbar'); + replacePattern = parseReplaceString('newfoo-newbar'); + actual = replacePattern.buildReplaceString(['foo-Bar'], true); + assert.equal(actual, 'newfoo-Newbar'); + + replacePattern = parseReplaceString('newfoo-newbar'); + actual = replacePattern.buildReplaceString(['foo-BAR'], true); + assert.equal(actual, 'newfoo-NEWBAR'); + replacePattern = parseReplaceString('newfoo_newbar'); actual = replacePattern.buildReplaceString(['Foo_Bar'], true); assert.equal(actual, 'Newfoo_Newbar'); @@ -242,5 +258,13 @@ suite('Replace Pattern test', () => { replacePattern = parseReplaceString('newfoo_newbar-abc'); actual = replacePattern.buildReplaceString(['Foo_Bar-abc'], true); assert.equal(actual, 'Newfoo_newbar-abc'); + + replacePattern = parseReplaceString('newfoo_newbar'); + actual = replacePattern.buildReplaceString(['foo_Bar'], true); + assert.equal(actual, 'newfoo_Newbar'); + + replacePattern = parseReplaceString('newfoo_newbar'); + actual = replacePattern.buildReplaceString(['foo_BAR'], true); + assert.equal(actual, 'newfoo_NEWBAR'); }); }); From 9341df363a6fbc5d3c4408f2e3f1cb4137d30a05 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Tue, 1 Oct 2019 11:36:11 -0700 Subject: [PATCH 051/435] add cancel id for custom dialog --- src/vs/workbench/services/dialogs/browser/dialogService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/dialogs/browser/dialogService.ts b/src/vs/workbench/services/dialogs/browser/dialogService.ts index 495d0ea725f..f67f9aa064c 100644 --- a/src/vs/workbench/services/dialogs/browser/dialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/dialogService.ts @@ -129,7 +129,7 @@ export class DialogService implements IDialogService { navigator.userAgent ); - const { choice } = await this.show(Severity.Info, this.productService.nameLong, [nls.localize('copy', "Copy"), nls.localize('ok', "OK")], { detail }); + const { choice } = await this.show(Severity.Info, this.productService.nameLong, [nls.localize('copy', "Copy"), nls.localize('ok', "OK")], { detail, cancelId: 1 }); if (choice === 0) { this.clipboardService.writeText(detail); From eedf80d84bef3c92b02f3a303bc3941de8493b88 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 11:57:19 -0700 Subject: [PATCH 052/435] Re-render image preview when image on disk changes Fixes #81751 Make sure we reload the image in the preview when it changes on disk --- extensions/image-preview/src/preview.ts | 32 ++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index b0f6ff4c357..7c3a1ad2a6c 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -13,10 +13,11 @@ export class Preview extends Disposable { public static readonly viewType = 'imagePreview.previewEditor'; private _active = true; + private _isWebviewDispose = false; constructor( private readonly extensionRoot: vscode.Uri, - resource: vscode.Uri, + private readonly resource: vscode.Uri, private readonly webviewEditor: vscode.WebviewEditor, private readonly sizeStatusBarEntry: SizeStatusBarEntry, private readonly zoomStatusBarEntry: ZoomStatusBarEntry, @@ -34,7 +35,9 @@ export class Preview extends Disposable { ] }; - webviewEditor.webview.html = this.getWebiewContents(webviewEditor, resource); + this._register(webviewEditor.onDidDispose(() => { + this._isWebviewDispose = true; + })); this._register(webviewEditor.webview.onDidReceiveMessage(message => { switch (message.type) { @@ -58,15 +61,31 @@ export class Preview extends Disposable { this._register(webviewEditor.onDidChangeViewState(() => { this.update(); })); + this._register(webviewEditor.onDidDispose(() => { if (this._active) { this.sizeStatusBarEntry.hide(); this.zoomStatusBarEntry.hide(); } })); + + const watcher = this._register(vscode.workspace.createFileSystemWatcher(resource.fsPath)); + this._register(watcher.onDidChange(e => { + if (e.toString() === this.resource.toString()) { + this.render(); + } + })); + + this.render(); this.update(); } + private render() { + if (!this._isWebviewDispose) { + this.webviewEditor.webview.html = this.getWebiewContents(); + } + } + private update() { this._active = this.webviewEditor.active; if (this._active) { @@ -78,10 +97,11 @@ export class Preview extends Disposable { } } - private getWebiewContents(webviewEditor: vscode.WebviewEditor, resource: vscode.Uri): string { + private getWebiewContents(): string { + const version = Date.now().toString(); const settings = { isMac: process.platform === 'darwin', - src: this.getResourcePath(webviewEditor, resource) + src: this.getResourcePath(this.webviewEditor, this.resource, version), }; return /* html */` @@ -102,12 +122,12 @@ export class Preview extends Disposable { `; } - private getResourcePath(webviewEditor: vscode.WebviewEditor, resource: vscode.Uri) { + private getResourcePath(webviewEditor: vscode.WebviewEditor, resource: vscode.Uri, version: string) { if (resource.scheme === 'data') { return encodeURI(resource.toString(true)); } - return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString(true)); + return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString(true) + `?version=${version}`); } private extensionResource(path: string) { From e1aa754e6f2a3da0feb840a96d24c790dc5991a2 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 1 Oct 2019 12:51:46 -0700 Subject: [PATCH 053/435] Fix #81790 --- src/vs/editor/contrib/codeAction/lightBulbWidget.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/contrib/codeAction/lightBulbWidget.css b/src/vs/editor/contrib/codeAction/lightBulbWidget.css index afacdc3d2ec..aadcb4fd6e6 100644 --- a/src/vs/editor/contrib/codeAction/lightBulbWidget.css +++ b/src/vs/editor/contrib/codeAction/lightBulbWidget.css @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +.monaco-editor .lightbulb-glyph, .monaco-editor .codicon-lightbulb { display: flex; align-items: center; @@ -12,6 +13,7 @@ padding-left: 2px; } +.monaco-editor .lightbulb-glyph:hover, .monaco-editor .codicon-lightbulb:hover { cursor: pointer; /* transform: scale(1.3, 1.3); */ From 197c7f27184a08666756ccda292dba5650d3033c Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 1 Oct 2019 12:58:46 -0700 Subject: [PATCH 054/435] Fix #81701 --- src/vs/workbench/browser/parts/editor/editorGroupView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index c1de6319db0..72708e0a4b9 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -289,7 +289,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { const removeGroupAction = this._register(new Action( CLOSE_EDITOR_GROUP_COMMAND_ID, localize('closeGroupAction', "Close"), - 'close-editor-group', + 'codicon-close', true, () => { this.accessor.removeGroup(this); From 00b1067cab71ab2bf574b3df7a2cd3c4dc3ff9a7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 13:44:54 -0700 Subject: [PATCH 055/435] Add simple description for image preview extension Fixes #81741 --- extensions/image-preview/README.md | 15 +++++++++++++++ extensions/image-preview/package.nls.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/extensions/image-preview/README.md b/extensions/image-preview/README.md index e8664c77a90..0a2d4f56512 100644 --- a/extensions/image-preview/README.md +++ b/extensions/image-preview/README.md @@ -1,3 +1,18 @@ # Image Preview **Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled. + +## Features + +This extension provides VS Code's built-in image preview functionality. + +Supported image formats: + +- `*.jpg`, `*.jpe`, `*.jpeg` +- `*.png` +- `*.bmp` +- `*.gif` +- `*.ico` +- `*.tga` +- `*.tif`, `*.tiff` +- `*.webp` diff --git a/extensions/image-preview/package.nls.json b/extensions/image-preview/package.nls.json index 78c753d1d54..44359cba8de 100644 --- a/extensions/image-preview/package.nls.json +++ b/extensions/image-preview/package.nls.json @@ -1,5 +1,5 @@ { "displayName": "Image Preview", - "description": "Previews images.", + "description": "Provides VS Code's built-in image preview", "webviewEditors.displayName": "Image Preview" } From 3793cb96e96c24f25d318d1cd162bfd3c15d96d9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 13:49:30 -0700 Subject: [PATCH 056/435] Improve docs on asExternalUri Fixes #81709 --- src/vs/vscode.proposed.d.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index a606623a3a1..99ddb4674fd 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1110,23 +1110,25 @@ declare module 'vscode' { //#endregion - // #region resolveExternalUri — mjbvz + // #region asExternalUri — mjbvz namespace env { /** * Resolves an *external* uri, such as a `http:` or `https:` link, from where the extension is running to a * uri to the same resource on the client machine. * - * This is a no-op if the extension is running locally. Currently only supports `https:` and `http:`. + * This is a no-op if the extension is running on the client machine. Currently only supports + * `https:` and `http:` uris. * - * If the extension is running remotely, this function automatically establishes port forwarding from - * the local machine to `target` on the remote and returns a local uri that can be used to for this connection. + * If the extension is running remotely, this function automatically establishes a port forwarding tunnel + * from the local machine to `target` on the remote and returns a local uri to the tunnel. The lifetime of + * the port fowarding tunnel is managed by VS Code and the tunnel can be closed by the user. * - * Extensions should not store the result of `resolveExternalUri` as the resolved uri may become invalid due to - * a system or user action — for example, in remote cases, a user may close a port that was forwarded by - * `resolveExternalUri`. + * Extensions should not cache the result of `asExternalUri` as the resolved uri may become invalid due to + * a system or user action — for example, in remote cases, a user may close a port forwardng tunnel + * that was opened by `asExternalUri`. * - * Note: uris passed through `openExternal` are automatically resolved and you should not call `resolveExternalUri` + * Note: uris passed through `openExternal` are automatically resolved and you should not call `asExternalUri` * on them. * * @return A uri that can be used on the client machine. From f96527a7bd8548bcf8d5447b544d64a26b55124c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:03:18 -0700 Subject: [PATCH 057/435] Document `mime` for custom editor selectors Fixes #81789 --- .../workbench/contrib/customEditor/browser/extensionPoint.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts index a17205467bb..b762769d89a 100644 --- a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts @@ -53,9 +53,9 @@ const webviewEditorsContribution: IJSONSchema = { type: 'string', description: nls.localize('contributes.selector.filenamePattern', 'Glob that the custom editor is enabled for.'), }, - scheme: { + mime: { type: 'string', - description: nls.localize('contributes.selector.scheme', 'File scheme that the custom editor is enabled for.'), + description: nls.localize('contributes.selector.mime', 'Glob that matches the mime type of a data uri resource.'), } } } From 73c61c4e40e949d0809f6f2882c273f9b849bf75 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Tue, 1 Oct 2019 14:04:15 -0700 Subject: [PATCH 058/435] Update high contrast minimap selection color, fixes #81728 --- src/vs/platform/theme/common/colorRegistry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index aae4462b6fc..fe1403f4ede 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -404,7 +404,7 @@ export const overviewRulerFindMatchForeground = registerColor('editorOverviewRul export const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.'), true); export const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hc: '#AB5A00' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true); -export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#f3f518' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the editor selection.'), true); +export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#ffffff' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the editor selection.'), true); // ----- color functions From dc5a137ec4406fd77a153e395eb03812e4536954 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 1 Oct 2019 14:08:34 -0700 Subject: [PATCH 059/435] Use US English in settings sync --- .../userDataSync/common/extensionsSync.ts | 14 +++++------ .../userDataSync/common/settingsSync.ts | 24 +++++++++---------- .../userDataSync/common/userDataSync.ts | 4 ++-- .../userDataSync/browser/userDataSync.ts | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index fbb4c595415..54fcb05a56c 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -70,16 +70,16 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser async sync(): Promise { if (!this.configurationService.getValue('configurationSync.enableExtensions')) { - this.logService.trace('Extensions: Skipping synchronising extensions as it is disabled.'); + this.logService.trace('Extensions: Skipping synchronizing extensions as it is disabled.'); return false; } if (this.status !== SyncStatus.Idle) { - this.logService.trace('Extensions: Skipping synchronising extensions as it is running already.'); + this.logService.trace('Extensions: Skipping synchronizing extensions as it is running already.'); return false; } - this.logService.trace('Extensions: Started synchronising extensions...'); + this.logService.trace('Extensions: Started synchronizing extensions...'); this.setStatus(SyncStatus.Syncing); try { @@ -88,13 +88,13 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('Extensions: Failed to synchronise extensions as there is a new remote version available. Synchronising again...'); + this.logService.info('Extensions: Failed to synchronise extensions as there is a new remote version available. Synchronizing again...'); return this.sync(); } throw e; } - this.logService.trace('Extensions: Finised synchronising extensions.'); + this.logService.trace('Extensions: Finised synchronizing extensions.'); this.setStatus(SyncStatus.Idle); return true; } @@ -129,7 +129,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser const { added, removed, updated, remote } = this.merge(localExtensions, remoteExtensions, lastSyncExtensions); if (!added.length && !removed.length && !updated.length && !remote) { - this.logService.trace('Extensions: No changes found during synchronising extensions.'); + this.logService.trace('Extensions: No changes found during synchronizing extensions.'); } if (added.length || removed.length || updated.length) { @@ -162,7 +162,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser const ignoredExtensions = this.configurationService.getValue('configurationSync.extensionsToIgnore') || []; // First time sync if (!remoteExtensions) { - this.logService.info('Extensions: Remote extensions does not exist. Synchronising extensions for the first time.'); + this.logService.info('Extensions: Remote extensions does not exist. Synchronizing extensions for the first time.'); return { added: [], removed: [], updated: [], remote: localExtensions.filter(({ identifier }) => ignoredExtensions.some(id => id.toLowerCase() === identifier.id.toLowerCase())) }; } diff --git a/src/vs/platform/userDataSync/common/settingsSync.ts b/src/vs/platform/userDataSync/common/settingsSync.ts index 69a7fb4f650..49f4176c018 100644 --- a/src/vs/platform/userDataSync/common/settingsSync.ts +++ b/src/vs/platform/userDataSync/common/settingsSync.ts @@ -81,27 +81,27 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { async sync(_continue?: boolean): Promise { if (!this.configurationService.getValue('configurationSync.enableSettings')) { - this.logService.trace('Settings: Skipping synchronising settings as it is disabled.'); + this.logService.trace('Settings: Skipping synchronizing settings as it is disabled.'); return false; } if (_continue) { - this.logService.info('Settings: Resumed synchronising settings'); + this.logService.info('Settings: Resumed synchronizing settings'); return this.continueSync(); } if (this.status !== SyncStatus.Idle) { - this.logService.trace('Settings: Skipping synchronising settings as it is running already.'); + this.logService.trace('Settings: Skipping synchronizing settings as it is running already.'); return false; } - this.logService.trace('Settings: Started synchronising settings...'); + this.logService.trace('Settings: Started synchronizing settings...'); this.setStatus(SyncStatus.Syncing); try { const result = await this.getPreview(); if (result.hasConflicts) { - this.logService.info('Settings: Detected conflicts while synchronising settings.'); + this.logService.info('Settings: Detected conflicts while synchronizing settings.'); this.setStatus(SyncStatus.HasConflicts); return false; } @@ -112,12 +112,12 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('Settings: Failed to synchronise settings as there is a new remote version available. Synchronising again...'); + this.logService.info('Settings: Failed to synchronise settings as there is a new remote version available. Synchronizing again...'); return this.sync(); } if (e instanceof FileSystemProviderError && e.code === FileSystemProviderErrorCode.FileExists) { // Rejected as there is a new local version. Syncing again. - this.logService.info('Settings: Failed to synchronise settings as there is a new local version available. Synchronising again...'); + this.logService.info('Settings: Failed to synchronise settings as there is a new local version available. Synchronizing again...'); return this.sync(); } throw e; @@ -128,7 +128,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { if (this.syncPreviewResultPromise) { this.syncPreviewResultPromise.cancel(); this.syncPreviewResultPromise = null; - this.logService.info('Settings: Stopped synchronising settings.'); + this.logService.info('Settings: Stopped synchronizing settings.'); } this.fileService.del(this.environmentService.settingsSyncPreviewResource); this.setStatus(SyncStatus.Idle); @@ -158,7 +158,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { let { fileContent, remoteUserData, hasLocalChanged, hasRemoteChanged } = await this.syncPreviewResultPromise; if (!hasLocalChanged && !hasRemoteChanged) { - this.logService.trace('Settings: No changes found during synchronising settings.'); + this.logService.trace('Settings: No changes found during synchronizing settings.'); } if (hasLocalChanged) { this.logService.info('Settings: Updating local settings'); @@ -178,10 +178,10 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { // Delete the preview await this.fileService.del(this.environmentService.settingsSyncPreviewResource); } else { - this.logService.trace('Settings: No changes found during synchronising settings.'); + this.logService.trace('Settings: No changes found during synchronizing settings.'); } - this.logService.trace('Settings: Finised synchronising settings.'); + this.logService.trace('Settings: Finised synchronizing settings.'); this.syncPreviewResultPromise = null; this.setStatus(SyncStatus.Idle); } @@ -235,7 +235,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { // First time syncing to remote else if (fileContent) { - this.logService.info('Settings: Remote settings does not exist. Synchronising settings for the first time.'); + this.logService.info('Settings: Remote settings does not exist. Synchronizing settings for the first time.'); hasRemoteChanged = true; previewContent = fileContent.value.toString(); } diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 6578b2a30b1..78e0f85879f 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -38,13 +38,13 @@ export function registerConfiguration(): IDisposable { }, 'configurationSync.enableSettings': { type: 'boolean', - description: localize('configurationSync.enableSettings', "When enabled settings are synchronised while synchronising configuration."), + description: localize('configurationSync.enableSettings', "When enabled settings are synchronised while synchronizing configuration."), default: true, scope: ConfigurationScope.APPLICATION, }, 'configurationSync.enableExtensions': { type: 'boolean', - description: localize('configurationSync.enableExtensions', "When enabled extensions are synchronised while synchronising configuration."), + description: localize('configurationSync.enableExtensions', "When enabled extensions are synchronised while synchronizing configuration."), default: true, scope: ConfigurationScope.APPLICATION, }, diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index ffbbcf5ebd5..92cb1c09c88 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -116,7 +116,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo } else if (this.userDataSyncService.status === SyncStatus.HasConflicts) { badge = new NumberBadge(1, () => localize('resolve conflicts', "Resolve Conflicts")); } else if (this.userDataSyncService.status === SyncStatus.Syncing) { - badge = new ProgressBadge(() => localize('syncing', "Synchronising User Configuration...")); + badge = new ProgressBadge(() => localize('syncing', "Synchronizing User Configuration...")); clazz = 'progress-badge'; } From ccf0a56243e2826043f2a3f42ea9f1cf40c601ba Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 1 Oct 2019 14:49:44 -0700 Subject: [PATCH 060/435] Fix #81704 --- src/vs/workbench/browser/actions/windowActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index 9a0bb2545e2..cb60384a583 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -37,7 +37,7 @@ export const inRecentFilesPickerContextKey = 'inRecentFilesPicker'; abstract class BaseOpenRecentAction extends Action { private removeFromRecentlyOpened: IQuickInputButton = { - iconClass: 'action-remove-from-recently-opened', + iconClass: 'codicon-close', tooltip: nls.localize('remove', "Remove from Recently Opened") }; From 64023bd18b86c8617b12fe08a7141575281fe2b8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:19:28 -0700 Subject: [PATCH 061/435] Show loading indicator while a custom editor is resolving Part of #81740 --- .../contrib/webview/browser/webviewEditorService.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index 5e48e6bc5da..bd865990708 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -258,7 +258,10 @@ export class WebviewEditorService implements IWebviewEditorService { ): Promise { const didRevive = await this.tryRevive(webview); if (!didRevive) { - this._revivalPool.add(webview, () => { }); + let resolve: () => void; + const promise = new Promise(r => { resolve = r; }); + this._revivalPool.add(webview, resolve!); + return promise; } } From af070ee0a0ee2c79599a05c3308d45ede9513d88 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:29:51 -0700 Subject: [PATCH 062/435] Move custom editor extension activation out of input Inputs should not need to know about extensions --- src/vs/workbench/api/browser/mainThreadWebview.ts | 1 + .../contrib/customEditor/browser/customEditorInput.ts | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index 207809e570f..c5e3d474583 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -96,6 +96,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews this._register(_webviewEditorService.registerResolver({ canResolve: (webview: WebviewInput) => { if (webview.getTypeId() === CustomFileEditorInput.typeId) { + extensionService.activateByEvent(`onWebviewEditor:${(webview as CustomFileEditorInput).viewType}`); return false; } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index ac4bc9dc18d..ecc7e62f361 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -16,7 +16,6 @@ import { ConfirmResult, IEditorInput, Verbosity } from 'vs/workbench/common/edit import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { promptSave } from 'vs/workbench/services/textfile/browser/textFileService'; export class CustomFileEditorInput extends WebviewInput { @@ -35,7 +34,6 @@ export class CustomFileEditorInput extends WebviewInput { webview: UnownedDisposable, @ILabelService private readonly labelService: ILabelService, @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, - @IExtensionService private readonly _extensionService: IExtensionService, @IDialogService private readonly dialogService: IDialogService, ) { super(id, viewType, '', webview); @@ -93,7 +91,6 @@ export class CustomFileEditorInput extends WebviewInput { public async resolve(): Promise { if (!this._hasResolved) { this._hasResolved = true; - this._extensionService.activateByEvent(`onWebviewEditor:${this.viewType}`); await this._webviewEditorService.resolveWebview(this); } return super.resolve(); From 214ee89df078b69ac31147e7bc552749330e8126 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:31:24 -0700 Subject: [PATCH 063/435] Use isEqual instead of tostring compare --- .../contrib/customEditor/browser/customEditorInput.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index ecc7e62f361..b5e56ab7456 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -7,6 +7,7 @@ import { memoize } from 'vs/base/common/decorators'; import { Emitter } from 'vs/base/common/event'; import { UnownedDisposable } from 'vs/base/common/lifecycle'; import { basename } from 'vs/base/common/path'; +import { isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { WebviewContentState } from 'vs/editor/common/modes'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -58,7 +59,7 @@ export class CustomFileEditorInput extends WebviewInput { matches(other: IEditorInput): boolean { return this === other || (other instanceof CustomFileEditorInput && this.viewType === other.viewType - && this.getResource().toString() === other.getResource().toString()); + && isEqual(this.getResource(), other.getResource())); } @memoize From 72c8590b3992a6259b175b5288b2dea34bb4a4f5 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:42:41 -0700 Subject: [PATCH 064/435] Make sure zoom status bar selections only effect the active image Fixes #81799 --- extensions/image-preview/src/preview.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 7c3a1ad2a6c..43a84751885 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -55,7 +55,9 @@ export class Preview extends Disposable { })); this._register(zoomStatusBarEntry.onDidChangeScale(e => { - this.webviewEditor.webview.postMessage({ type: 'setScale', scale: e.scale }); + if (this._active && !this._isWebviewDispose) { + this.webviewEditor.webview.postMessage({ type: 'setScale', scale: e.scale }); + } })); this._register(webviewEditor.onDidChangeViewState(() => { From 6493b8dc0a2c322cca8efec23136987a97212747 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:44:45 -0700 Subject: [PATCH 065/435] Make sure active is set to false when webviews are disposed --- extensions/image-preview/src/preview.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 43a84751885..27c1d7cba14 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -65,6 +65,8 @@ export class Preview extends Disposable { })); this._register(webviewEditor.onDidDispose(() => { + this._isWebviewDispose = true; + this._active = false; if (this._active) { this.sizeStatusBarEntry.hide(); this.zoomStatusBarEntry.hide(); From b3da545c1d924c536dfef1bbb7788352b1aa4451 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:48:11 -0700 Subject: [PATCH 066/435] Use enum to track preview state to avoid getting into invalid states such as active & disposed --- extensions/image-preview/src/preview.ts | 31 ++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 27c1d7cba14..fe70bf92c95 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -8,12 +8,17 @@ import { SizeStatusBarEntry } from './sizeStatusBarEntry'; import { ZoomStatusBarEntry } from './zoomStatusBarEntry'; import { Disposable } from './dispose'; +const enum PreviewState { + Disposed, + Visible, + Active, +} + export class Preview extends Disposable { public static readonly viewType = 'imagePreview.previewEditor'; - private _active = true; - private _isWebviewDispose = false; + private _previewState = PreviewState.Visible; constructor( private readonly extensionRoot: vscode.Uri, @@ -35,10 +40,6 @@ export class Preview extends Disposable { ] }; - this._register(webviewEditor.onDidDispose(() => { - this._isWebviewDispose = true; - })); - this._register(webviewEditor.webview.onDidReceiveMessage(message => { switch (message.type) { case 'size': @@ -55,7 +56,7 @@ export class Preview extends Disposable { })); this._register(zoomStatusBarEntry.onDidChangeScale(e => { - if (this._active && !this._isWebviewDispose) { + if (this._previewState === PreviewState.Active) { this.webviewEditor.webview.postMessage({ type: 'setScale', scale: e.scale }); } })); @@ -65,12 +66,11 @@ export class Preview extends Disposable { })); this._register(webviewEditor.onDidDispose(() => { - this._isWebviewDispose = true; - this._active = false; - if (this._active) { + if (this._previewState === PreviewState.Active) { this.sizeStatusBarEntry.hide(); this.zoomStatusBarEntry.hide(); } + this._previewState = PreviewState.Disposed; })); const watcher = this._register(vscode.workspace.createFileSystemWatcher(resource.fsPath)); @@ -85,17 +85,22 @@ export class Preview extends Disposable { } private render() { - if (!this._isWebviewDispose) { + if (this._previewState !== PreviewState.Disposed) { this.webviewEditor.webview.html = this.getWebiewContents(); } } private update() { - this._active = this.webviewEditor.active; - if (this._active) { + if (this._previewState === PreviewState.Disposed) { + return; + } + + if (this.webviewEditor.active) { + this._previewState = PreviewState.Active; this.sizeStatusBarEntry.show(); this.zoomStatusBarEntry.show(); } else { + this._previewState = PreviewState.Visible; this.sizeStatusBarEntry.hide(); this.zoomStatusBarEntry.hide(); } From 47ac64a019b340e129ec40906fd82054efd438ab Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 14:53:37 -0700 Subject: [PATCH 067/435] Make sure status bar name for zoom/size can be localized --- extensions/image-preview/src/sizeStatusBarEntry.ts | 7 +++++-- extensions/image-preview/src/zoomStatusBarEntry.ts | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/extensions/image-preview/src/sizeStatusBarEntry.ts b/extensions/image-preview/src/sizeStatusBarEntry.ts index 88f75f0cfd6..acb2d260939 100644 --- a/extensions/image-preview/src/sizeStatusBarEntry.ts +++ b/extensions/image-preview/src/sizeStatusBarEntry.ts @@ -5,6 +5,9 @@ import * as vscode from 'vscode'; import { Disposable } from './dispose'; +import * as nls from 'vscode-nls'; + +const localize = nls.loadMessageBundle(); export class SizeStatusBarEntry extends Disposable { private readonly _entry: vscode.StatusBarItem; @@ -13,7 +16,7 @@ export class SizeStatusBarEntry extends Disposable { super(); this._entry = this._register(vscode.window.createStatusBarItem({ id: 'imagePreview.size', - name: 'Image Size', + name: localize('sizeStatusBar.name', "Image Size"), alignment: vscode.StatusBarAlignment.Right, priority: 101 /* to the left of editor status (100) */, })); @@ -30,4 +33,4 @@ export class SizeStatusBarEntry extends Disposable { public update(text: string) { this._entry.text = text; } -} \ No newline at end of file +} diff --git a/extensions/image-preview/src/zoomStatusBarEntry.ts b/extensions/image-preview/src/zoomStatusBarEntry.ts index 11580b84299..68b19232701 100644 --- a/extensions/image-preview/src/zoomStatusBarEntry.ts +++ b/extensions/image-preview/src/zoomStatusBarEntry.ts @@ -23,7 +23,7 @@ export class ZoomStatusBarEntry extends Disposable { super(); this._entry = this._register(vscode.window.createStatusBarItem({ id: 'imagePreview.zoom', - name: 'Image Zoom', + name: localize('zoomStatusBar.name', "Image Zoom"), alignment: vscode.StatusBarAlignment.Right, priority: 102 /* to the left of editor size entry (101) */, })); @@ -65,4 +65,4 @@ export class ZoomStatusBarEntry extends Disposable { ? localize('zoomStatusBar.wholeImageLabel', "Whole Image") : `${Math.round(scale * 100)}%`; } -} \ No newline at end of file +} From c241e1d5e49493326e2c4169fc79a34232d8cb42 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 15:05:10 -0700 Subject: [PATCH 068/435] Making status bar items for images more reliable Fixes #81738 --- extensions/image-preview/src/preview.ts | 39 ++++++++++++------- .../image-preview/src/sizeStatusBarEntry.ts | 17 ++++---- .../image-preview/src/zoomStatusBarEntry.ts | 19 +++++---- 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index fe70bf92c95..b3c050587a1 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import { SizeStatusBarEntry } from './sizeStatusBarEntry'; -import { ZoomStatusBarEntry } from './zoomStatusBarEntry'; +import { ZoomStatusBarEntry, Scale } from './zoomStatusBarEntry'; import { Disposable } from './dispose'; const enum PreviewState { @@ -18,7 +18,11 @@ export class Preview extends Disposable { public static readonly viewType = 'imagePreview.previewEditor'; + private readonly id: string = `${Date.now()}-${Math.random().toString()}`; + private _previewState = PreviewState.Visible; + private _imageSize: string | undefined; + private _imageZoom: Scale | undefined; constructor( private readonly extensionRoot: vscode.Uri, @@ -44,12 +48,14 @@ export class Preview extends Disposable { switch (message.type) { case 'size': { - this.sizeStatusBarEntry.update(message.value); + this._imageSize = message.value; + this.update(); break; } case 'zoom': { - this.zoomStatusBarEntry.update(message.value); + this._imageZoom = message.value; + this.update(); break; } } @@ -67,8 +73,8 @@ export class Preview extends Disposable { this._register(webviewEditor.onDidDispose(() => { if (this._previewState === PreviewState.Active) { - this.sizeStatusBarEntry.hide(); - this.zoomStatusBarEntry.hide(); + this.sizeStatusBarEntry.hide(this.id); + this.zoomStatusBarEntry.hide(this.id); } this._previewState = PreviewState.Disposed; })); @@ -97,12 +103,14 @@ export class Preview extends Disposable { if (this.webviewEditor.active) { this._previewState = PreviewState.Active; - this.sizeStatusBarEntry.show(); - this.zoomStatusBarEntry.show(); + this.sizeStatusBarEntry.show(this.id, this._imageSize || ''); + this.zoomStatusBarEntry.show(this.id, this._imageZoom || 'fit'); } else { + if (this._previewState === PreviewState.Active) { + this.sizeStatusBarEntry.hide(this.id); + this.zoomStatusBarEntry.hide(this.id); + } this._previewState = PreviewState.Visible; - this.sizeStatusBarEntry.hide(); - this.zoomStatusBarEntry.hide(); } } @@ -132,11 +140,16 @@ export class Preview extends Disposable { } private getResourcePath(webviewEditor: vscode.WebviewEditor, resource: vscode.Uri, version: string) { - if (resource.scheme === 'data') { - return encodeURI(resource.toString(true)); - } + switch (resource.scheme) { + case 'data': + return encodeURI(resource.toString(true)); - return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString(true) + `?version=${version}`); + case 'git': + + + default: + return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString(true) + `?version=${version}`); + } } private extensionResource(path: string) { diff --git a/extensions/image-preview/src/sizeStatusBarEntry.ts b/extensions/image-preview/src/sizeStatusBarEntry.ts index acb2d260939..6b2bff746cf 100644 --- a/extensions/image-preview/src/sizeStatusBarEntry.ts +++ b/extensions/image-preview/src/sizeStatusBarEntry.ts @@ -12,6 +12,8 @@ const localize = nls.loadMessageBundle(); export class SizeStatusBarEntry extends Disposable { private readonly _entry: vscode.StatusBarItem; + private _showingOwner: string | undefined; + constructor() { super(); this._entry = this._register(vscode.window.createStatusBarItem({ @@ -22,15 +24,16 @@ export class SizeStatusBarEntry extends Disposable { })); } - public show() { + public show(owner: string, text: string) { + this._showingOwner = owner; + this._entry.text = text; this._entry.show(); } - public hide() { - this._entry.hide(); - } - - public update(text: string) { - this._entry.text = text; + public hide(owner: string) { + if (owner === this._showingOwner) { + this._entry.hide(); + this._showingOwner = undefined; + } } } diff --git a/extensions/image-preview/src/zoomStatusBarEntry.ts b/extensions/image-preview/src/zoomStatusBarEntry.ts index 68b19232701..dc102a48d64 100644 --- a/extensions/image-preview/src/zoomStatusBarEntry.ts +++ b/extensions/image-preview/src/zoomStatusBarEntry.ts @@ -11,7 +11,7 @@ const localize = nls.loadMessageBundle(); const selectZoomLevelCommandId = '_imagePreview.selectZoomLevel'; -type Scale = number | 'fit'; +export type Scale = number | 'fit'; export class ZoomStatusBarEntry extends Disposable { private readonly _entry: vscode.StatusBarItem; @@ -19,6 +19,8 @@ export class ZoomStatusBarEntry extends Disposable { private readonly _onDidChangeScale = this._register(new vscode.EventEmitter<{ scale: Scale }>()); public readonly onDidChangeScale = this._onDidChangeScale.event; + private _showOwner: string | undefined; + constructor() { super(); this._entry = this._register(vscode.window.createStatusBarItem({ @@ -48,16 +50,17 @@ export class ZoomStatusBarEntry extends Disposable { this._entry.command = selectZoomLevelCommandId; } - public show() { + public show(owner: string, scale: Scale) { + this._showOwner = owner; + this._entry.text = this.zoomLabel(scale); this._entry.show(); } - public hide() { - this._entry.hide(); - } - - public update(scale: Scale) { - this._entry.text = this.zoomLabel(scale); + public hide(owner: string) { + if (owner === this._showOwner) { + this._entry.hide(); + this._showOwner = undefined; + } } private zoomLabel(scale: Scale): string { From aeae28bf2cbc8cbe7e0a90b97c195c6935348b24 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 15:41:56 -0700 Subject: [PATCH 069/435] Remove tiff as a supported image preview format Fixes #81803 This is not supported by chromium --- extensions/image-preview/README.md | 1 - extensions/image-preview/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/image-preview/README.md b/extensions/image-preview/README.md index 0a2d4f56512..ccb5ac3954a 100644 --- a/extensions/image-preview/README.md +++ b/extensions/image-preview/README.md @@ -14,5 +14,4 @@ Supported image formats: - `*.gif` - `*.ico` - `*.tga` -- `*.tif`, `*.tiff` - `*.webp` diff --git a/extensions/image-preview/package.json b/extensions/image-preview/package.json index 7db7b2fb17e..7dd872ae1bc 100644 --- a/extensions/image-preview/package.json +++ b/extensions/image-preview/package.json @@ -26,7 +26,7 @@ "displayName": "%webviewEditors.displayName%", "selector": [ { - "filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,tga,tif,tiff,webp}", + "filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,tga,webp}", "mime": "image/*" } ] From 04d0cf6ad6ce2c18afc651e7ba13c97827ae3d6f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 16:17:48 -0700 Subject: [PATCH 070/435] Show errors when image can't be loaded For #81803 --- extensions/image-preview/media/main.css | 29 ++++++++++++++++++++----- extensions/image-preview/media/main.js | 16 ++++++++------ extensions/image-preview/src/preview.ts | 12 ++++++---- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/extensions/image-preview/media/main.css b/extensions/image-preview/media/main.css index 971a641fb07..57dface9cad 100644 --- a/extensions/image-preview/media/main.css +++ b/extensions/image-preview/media/main.css @@ -6,6 +6,7 @@ html, body { height: 100%; max-height: 100%; + text-align: center; } body img { @@ -77,18 +78,34 @@ body img { margin-left: 5px; } -.loading { - position: fixed; +.container.loading, +.container.error { + display: flex; + justify-content: center; + align-items: center; +} + +.loading-indicator { width: 30px; height: 30px; - left: 50%; - top: 50%; - margin-top: -15px; - margin-left: -15px; background-image: url('./loading.svg'); background-size: cover; } +.loading-indicator, +.image-load-error-message { + display: none; +} + +.loading .loading-indicator, +.error .image-load-error-message { + display: block; +} + +.image-load-error-message { + margin: 1em; +} + .vscode-dark .loading { background-image: url('./loading-dark.svg'); } diff --git a/extensions/image-preview/media/main.js b/extensions/image-preview/media/main.js index e58b7e58f36..cd39eb9a53f 100644 --- a/extensions/image-preview/media/main.js +++ b/extensions/image-preview/media/main.js @@ -72,7 +72,7 @@ let hasLoadedImage = false; // Elements - const container = /** @type {HTMLElement} */(document.querySelector('body')); + const container = document.body; const image = document.createElement('img'); function updateScale(newScale) { @@ -232,19 +232,15 @@ image.classList.add('scale-to-fit'); image.addEventListener('load', () => { - document.querySelector('.loading').remove(); hasLoadedImage = true; - if (!image) { - return; - } - vscode.postMessage({ type: 'size', value: `${image.naturalWidth}x${image.naturalHeight}`, }); - container.classList.add('ready'); + document.body.classList.remove('loading'); + document.body.classList.add('ready'); document.body.append(image); updateScale(scale); @@ -254,6 +250,12 @@ } }); + image.addEventListener('error', () => { + hasLoadedImage = true; + document.body.classList.add('error'); + document.body.classList.remove('loading'); + }); + image.src = decodeURI(settings.src); window.addEventListener('message', e => { diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index b3c050587a1..007697fffc5 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -4,9 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { SizeStatusBarEntry } from './sizeStatusBarEntry'; -import { ZoomStatusBarEntry, Scale } from './zoomStatusBarEntry'; +import * as nls from 'vscode-nls'; import { Disposable } from './dispose'; +import { SizeStatusBarEntry } from './sizeStatusBarEntry'; +import { Scale, ZoomStatusBarEntry } from './zoomStatusBarEntry'; + +const localize = nls.loadMessageBundle(); const enum PreviewState { Disposed, @@ -132,8 +135,9 @@ export class Preview extends Disposable { - -
+ +
+
${localize('preview.imageLoadError', "An error occurred while loading the image")}
`; From f735e062f301fef3d7cc029a23a923a88dfb8426 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 16:39:30 -0700 Subject: [PATCH 071/435] Rename custom editors discretion to priority Fixes #81785 --- .../customEditor/browser/customEditors.ts | 8 ++++---- .../customEditor/browser/extensionPoint.ts | 18 +++++++++--------- .../customEditor/common/customEditor.ts | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 852e62956cd..20930bf6242 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -22,7 +22,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { EditorInput, EditorOptions, IEditor, IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { webviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint'; -import { CustomEditorDiscretion, CustomEditorInfo, CustomEditorSelector, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { CustomEditorPriority, CustomEditorInfo, CustomEditorSelector, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -37,7 +37,7 @@ const defaultEditorInfo: CustomEditorInfo = { selector: [ { filenamePattern: '*' } ], - discretion: CustomEditorDiscretion.default, + priority: CustomEditorPriority.default, }; export class CustomEditorStore { @@ -88,7 +88,7 @@ export class CustomEditorService implements ICustomEditorService { id: webviewEditorContribution.viewType, displayName: webviewEditorContribution.displayName, selector: webviewEditorContribution.selector || [], - discretion: webviewEditorContribution.discretion || CustomEditorDiscretion.default, + priority: webviewEditorContribution.priority || CustomEditorPriority.default, }); } } @@ -231,7 +231,7 @@ export class CustomEditorContribution implements IWorkbenchContribution { return; } - const defaultEditors = contributedEditors.filter(editor => editor.discretion === CustomEditorDiscretion.default); + const defaultEditors = contributedEditors.filter(editor => editor.priority === CustomEditorPriority.default); if (defaultEditors.length === 1) { return { override: this.customEditorService.openWith(resource, defaultEditors[0].id, options, group), diff --git a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts index b762769d89a..c5c85509532 100644 --- a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts @@ -5,7 +5,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import * as nls from 'vs/nls'; -import { CustomEditorDiscretion, CustomEditorSelector } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { CustomEditorPriority, CustomEditorSelector } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { languagesExtPoint } from 'vs/workbench/services/mode/common/workbenchModeService'; @@ -13,14 +13,14 @@ namespace WebviewEditorContribution { export const viewType = 'viewType'; export const displayName = 'displayName'; export const selector = 'selector'; - export const discretion = 'discretion'; + export const priority = 'priority'; } interface IWebviewEditorsExtensionPoint { readonly [WebviewEditorContribution.viewType]: string; readonly [WebviewEditorContribution.displayName]: string; readonly [WebviewEditorContribution.selector]?: readonly CustomEditorSelector[]; - readonly [WebviewEditorContribution.discretion]?: CustomEditorDiscretion; + readonly [WebviewEditorContribution.priority]?: CustomEditorPriority; } const webviewEditorsContribution: IJSONSchema = { @@ -60,16 +60,16 @@ const webviewEditorsContribution: IJSONSchema = { } } }, - [WebviewEditorContribution.discretion]: { + [WebviewEditorContribution.priority]: { type: 'string', - description: nls.localize('contributes.discretion', 'Controls when the custom editor is used. May be overridden by users.'), + description: nls.localize('contributes.priority', 'Controls when the custom editor is used. May be overridden by users.'), enum: [ - CustomEditorDiscretion.default, - CustomEditorDiscretion.option + CustomEditorPriority.default, + CustomEditorPriority.option ], enumDescriptions: [ - nls.localize('contributes.discretion.default', 'Editor is automatically used for a resource if no other default custom editors are registered for it.'), - nls.localize('contributes.discretion.option', 'Editor is not automatically used but can be selected by a user.'), + nls.localize('contributes.priority.default', 'Editor is automatically used for a resource if no other default custom editors are registered for it.'), + nls.localize('contributes.priority.option', 'Editor is not automatically used but can be selected by a user.'), ], default: 'default' } diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index a6e1c1d4b37..699441fc7da 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -23,7 +23,7 @@ export interface ICustomEditorService { promptOpenWith(resource: URI, options?: ITextEditorOptions, group?: IEditorGroup): Promise; } -export const enum CustomEditorDiscretion { +export const enum CustomEditorPriority { default = 'default', option = 'option', } @@ -36,6 +36,6 @@ export interface CustomEditorSelector { export interface CustomEditorInfo { readonly id: string; readonly displayName: string; - readonly discretion: CustomEditorDiscretion; + readonly priority: CustomEditorPriority; readonly selector: readonly CustomEditorSelector[]; } From a25c6e6660b2025938a4792c8c1e926986b2c6fa Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 17:00:00 -0700 Subject: [PATCH 072/435] Add CSP --- extensions/image-preview/src/preview.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 007697fffc5..2eb566281c5 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -124,6 +124,8 @@ export class Preview extends Disposable { src: this.getResourcePath(this.webviewEditor, this.resource, version), }; + const nonce = Date.now().toString(); + return /* html */` @@ -131,14 +133,16 @@ export class Preview extends Disposable { Image Preview - + + +
${localize('preview.imageLoadError', "An error occurred while loading the image")}
- + `; } From c057a4b9c73ce820e0c1a02797bf9f06bd638e86 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 17:09:46 -0700 Subject: [PATCH 073/435] Make sure we dispose of any custom editor inputs when replacing them Fixes #81773 --- .../workbench/contrib/customEditor/browser/customEditors.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 20930bf6242..21a77e1b3a1 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -179,6 +179,12 @@ export class CustomEditorService implements ICustomEditorService { replacement: input, options: options ? EditorOptions.create(options) : undefined, }], group); + + for (const editor of existingEditors) { + if (editor instanceof CustomFileEditorInput) { + editor.dispose(); + } + } } } return this.editorService.openEditor(input, options, group); From 8eaec303ea9b12291540e729ad32b930169e67a4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 21:50:08 -0700 Subject: [PATCH 074/435] Revert "Make sure we dispose of any custom editor inputs when replacing them" This reverts commit c057a4b9c73ce820e0c1a02797bf9f06bd638e86. --- .../workbench/contrib/customEditor/browser/customEditors.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 21a77e1b3a1..20930bf6242 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -179,12 +179,6 @@ export class CustomEditorService implements ICustomEditorService { replacement: input, options: options ? EditorOptions.create(options) : undefined, }], group); - - for (const editor of existingEditors) { - if (editor instanceof CustomFileEditorInput) { - editor.dispose(); - } - } } } return this.editorService.openEditor(input, options, group); From 3f21572d6afe7f3a3d746243be599435fd40878f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 09:54:18 +0200 Subject: [PATCH 075/435] comment out test --- .../src/singlefolder-tests/commands.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index 7dba2cfa93c..463d63c1aa6 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -104,13 +104,13 @@ suite('commands namespace tests', () => { return Promise.all([a, b, c, d, e]); }); - test('api-command: vscode.open', function () { - let uri = Uri.parse(workspace.workspaceFolders![0].uri.toString() + '/image.png'); - let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false)); - let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false)); - let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true)); - let d = commands.executeCommand('vscode.open', uri, true).then(() => assert.ok(false), () => assert.ok(true)); + // test('api-command: vscode.open', function () { + // let uri = Uri.parse(workspace.workspaceFolders![0].uri.toString() + '/image.png'); + // let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false)); + // let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false)); + // let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true)); + // let d = commands.executeCommand('vscode.open', uri, true).then(() => assert.ok(false), () => assert.ok(true)); - return Promise.all([a, b, c, d]); - }); + // return Promise.all([a, b, c, d]); + // }); }); From 695ee74864ef93d10f5de0861cb66af190e76211 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 10:28:17 +0200 Subject: [PATCH 076/435] doh --- .../vscode-api-tests/src/singlefolder-tests/commands.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index 463d63c1aa6..7b2562ce51d 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -6,7 +6,7 @@ import 'mocha'; import * as assert from 'assert'; import { join } from 'path'; -import { commands, workspace, window, Uri, ViewColumn, Range, Position } from 'vscode'; +import { commands, workspace, window, Uri, Range, Position } from 'vscode'; suite('commands namespace tests', () => { From ff42be5d562636b911bde8d5b551562b9a927f66 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 10:42:51 +0200 Subject: [PATCH 077/435] remove 64 bit suggestion fixes #81792 --- .../electron-browser/update.contribution.ts | 18 --------- .../contrib/update/electron-browser/update.ts | 40 ------------------- src/vs/workbench/workbench.desktop.main.ts | 3 -- 3 files changed, 61 deletions(-) delete mode 100644 src/vs/workbench/contrib/update/electron-browser/update.contribution.ts delete mode 100644 src/vs/workbench/contrib/update/electron-browser/update.ts diff --git a/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts b/src/vs/workbench/contrib/update/electron-browser/update.contribution.ts deleted file mode 100644 index 26a9151d09c..00000000000 --- a/src/vs/workbench/contrib/update/electron-browser/update.contribution.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 * as platform from 'vs/base/common/platform'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { Win3264BitContribution } from 'vs/workbench/contrib/update/electron-browser/update'; -import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; - -const workbench = Registry.as(WorkbenchExtensions.Workbench); - -if (platform.isWindows) { - if (process.arch === 'ia32') { - workbench.registerWorkbenchContribution(Win3264BitContribution, LifecyclePhase.Restored); - } -} diff --git a/src/vs/workbench/contrib/update/electron-browser/update.ts b/src/vs/workbench/contrib/update/electron-browser/update.ts deleted file mode 100644 index b8fbf48c2de..00000000000 --- a/src/vs/workbench/contrib/update/electron-browser/update.ts +++ /dev/null @@ -1,40 +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 * as nls from 'vs/nls'; -import severity from 'vs/base/common/severity'; -import product from 'vs/platform/product/common/product'; -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { INotificationService } from 'vs/platform/notification/common/notification'; - -export class Win3264BitContribution implements IWorkbenchContribution { - - private static readonly URL = 'https://code.visualstudio.com/updates/v1_15#_windows-64-bit'; - private static readonly INSIDER_URL = 'https://github.com/Microsoft/vscode-docs/blob/vnext/release-notes/v1_15.md#windows-64-bit'; - - constructor( - @INotificationService notificationService: INotificationService, - @IEnvironmentService environmentService: IEnvironmentService - ) { - if (environmentService.disableUpdates) { - return; - } - - const url = product.quality === 'insider' - ? Win3264BitContribution.INSIDER_URL - : Win3264BitContribution.URL; - - notificationService.prompt( - severity.Info, - nls.localize('64bitisavailable', "{0} for 64-bit Windows is now available! Click [here]({1}) to learn more.", product.nameShort, url), - [], - { - sticky: true, - neverShowAgain: { id: 'neverShowAgain:update/win32-64bits', isSecondary: true } - } - ); - } -} diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index 3dd3700dc0d..ee57288fc95 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -111,9 +111,6 @@ import 'vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution // Execution import 'vs/workbench/contrib/externalTerminal/node/externalTerminalService'; -// Update -import 'vs/workbench/contrib/update/electron-browser/update.contribution'; - // Performance import 'vs/workbench/contrib/performance/electron-browser/performance.contribution'; From 46098598feb53f19b4fdfb67dfc20f5e86548043 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 10:48:17 +0200 Subject: [PATCH 078/435] fix #81137 --- .../editor/contrib/snippet/snippetSession.ts | 4 ++-- .../contrib/snippet/snippetVariables.ts | 13 ++++++---- .../snippet/test/snippetVariables.test.ts | 24 +++++++++---------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts index 8bc84ccfd52..91cf566e742 100644 --- a/src/vs/editor/contrib/snippet/snippetSession.ts +++ b/src/vs/editor/contrib/snippet/snippetSession.ts @@ -392,7 +392,7 @@ export class SnippetSession { const modelBasedVariableResolver = editor.invokeWithinContext(accessor => new ModelBasedVariableResolver(accessor.get(ILabelService, optional), model)); const clipboardService = editor.invokeWithinContext(accessor => accessor.get(IClipboardService, optional)); - clipboardText = clipboardText || clipboardService && clipboardService.readTextSync(); + const readClipboardText = () => clipboardText || clipboardService && clipboardService.readTextSync(); let delta = 0; @@ -445,7 +445,7 @@ export class SnippetSession { snippet.resolveVariables(new CompositeSnippetVariableResolver([ modelBasedVariableResolver, - new ClipboardBasedVariableResolver(clipboardText, idx, indexedSelections.length, editor.getOption(EditorOption.multiCursorPaste) === 'spread'), + new ClipboardBasedVariableResolver(readClipboardText, idx, indexedSelections.length, editor.getOption(EditorOption.multiCursorPaste) === 'spread'), new SelectionBasedVariableResolver(model, selection), new CommentBasedVariableResolver(model), new TimeBasedVariableResolver, diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index 4f289c2af95..1decd3c754d 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -164,10 +164,14 @@ export class ModelBasedVariableResolver implements VariableResolver { } } +export interface IReadClipboardText { + (): string | undefined; +} + export class ClipboardBasedVariableResolver implements VariableResolver { constructor( - private readonly _clipboardText: string | undefined, + private readonly _readClipboardText: IReadClipboardText, private readonly _selectionIdx: number, private readonly _selectionCount: number, private readonly _spread: boolean @@ -180,7 +184,8 @@ export class ClipboardBasedVariableResolver implements VariableResolver { return undefined; } - if (!this._clipboardText) { + const clipboardText = this._readClipboardText(); + if (!clipboardText) { return undefined; } @@ -188,12 +193,12 @@ export class ClipboardBasedVariableResolver implements VariableResolver { // text whenever there the line count equals the cursor count // and when enabled if (this._spread) { - const lines = this._clipboardText.split(/\r\n|\n|\r/).filter(s => !isFalsyOrWhitespace(s)); + const lines = clipboardText.split(/\r\n|\n|\r/).filter(s => !isFalsyOrWhitespace(s)); if (lines.length === this._selectionCount) { return lines[this._selectionIdx]; } } - return this._clipboardText; + return clipboardText; } } export class CommentBasedVariableResolver implements VariableResolver { diff --git a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts index 0189cc0de2e..b3807f632cb 100644 --- a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts @@ -236,28 +236,28 @@ suite('Snippet Variables Resolver', function () { test('Add variable to insert value from clipboard to a snippet #40153', function () { - assertVariableResolve(new ClipboardBasedVariableResolver(undefined, 1, 0, true), 'CLIPBOARD', undefined); + assertVariableResolve(new ClipboardBasedVariableResolver(() => undefined, 1, 0, true), 'CLIPBOARD', undefined); - assertVariableResolve(new ClipboardBasedVariableResolver(null!, 1, 0, true), 'CLIPBOARD', undefined); + assertVariableResolve(new ClipboardBasedVariableResolver(() => null!, 1, 0, true), 'CLIPBOARD', undefined); - assertVariableResolve(new ClipboardBasedVariableResolver('', 1, 0, true), 'CLIPBOARD', undefined); + assertVariableResolve(new ClipboardBasedVariableResolver(() => '', 1, 0, true), 'CLIPBOARD', undefined); - assertVariableResolve(new ClipboardBasedVariableResolver('foo', 1, 0, true), 'CLIPBOARD', 'foo'); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'foo', 1, 0, true), 'CLIPBOARD', 'foo'); - assertVariableResolve(new ClipboardBasedVariableResolver('foo', 1, 0, true), 'foo', undefined); - assertVariableResolve(new ClipboardBasedVariableResolver('foo', 1, 0, true), 'cLIPBOARD', undefined); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'foo', 1, 0, true), 'foo', undefined); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'foo', 1, 0, true), 'cLIPBOARD', undefined); }); test('Add variable to insert value from clipboard to a snippet #40153', function () { - assertVariableResolve(new ClipboardBasedVariableResolver('line1', 1, 2, true), 'CLIPBOARD', 'line1'); - assertVariableResolve(new ClipboardBasedVariableResolver('line1\nline2\nline3', 1, 2, true), 'CLIPBOARD', 'line1\nline2\nline3'); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'line1', 1, 2, true), 'CLIPBOARD', 'line1'); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'line1\nline2\nline3', 1, 2, true), 'CLIPBOARD', 'line1\nline2\nline3'); - assertVariableResolve(new ClipboardBasedVariableResolver('line1\nline2', 1, 2, true), 'CLIPBOARD', 'line2'); - resolver = new ClipboardBasedVariableResolver('line1\nline2', 0, 2, true); - assertVariableResolve(new ClipboardBasedVariableResolver('line1\nline2', 0, 2, true), 'CLIPBOARD', 'line1'); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'line1\nline2', 1, 2, true), 'CLIPBOARD', 'line2'); + resolver = new ClipboardBasedVariableResolver(() => 'line1\nline2', 0, 2, true); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'line1\nline2', 0, 2, true), 'CLIPBOARD', 'line1'); - assertVariableResolve(new ClipboardBasedVariableResolver('line1\nline2', 0, 2, false), 'CLIPBOARD', 'line1\nline2'); + assertVariableResolve(new ClipboardBasedVariableResolver(() => 'line1\nline2', 0, 2, false), 'CLIPBOARD', 'line1\nline2'); }); From b0aecd3843c1d6d9dc09117a2c354f027f609258 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Oct 2019 11:03:04 +0200 Subject: [PATCH 079/435] handle auth errors --- .../userDataSync/common/userDataSync.ts | 1 + .../userDataSync/common/userDataSyncService.ts | 17 ++++++++++++----- .../common/userDataSyncStoreService.ts | 12 ++++++------ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 78e0f85879f..0ac8e4c8373 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -91,6 +91,7 @@ export interface IUserData { } export enum UserDataSyncStoreErrorCode { + Unauthroized = 'Unauthroized', Rejected = 'Rejected', Unknown = 'Unknown' } diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index 8c7d6684359..69823ebce3c 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IUserDataSyncService, SyncStatus, ISynchroniser, IUserDataSyncStoreService, SyncSource, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, SyncStatus, ISynchroniser, IUserDataSyncStoreService, SyncSource, IUserDataSyncLogService, UserDataSyncStoreError, UserDataSyncStoreErrorCode } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync'; @@ -127,7 +127,7 @@ export class UserDataAutoSync extends Disposable { @IConfigurationService private readonly configurationService: IConfigurationService, @IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService, @IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService, - @IUserDataSyncLogService private readonly userDataSyncLogService: IUserDataSyncLogService, + @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, @IAuthTokenService private readonly authTokenService: IAuthTokenService, ) { super(); @@ -147,13 +147,13 @@ export class UserDataAutoSync extends Disposable { this.enabled = enabled; if (this.enabled) { - this.userDataSyncLogService.info('Syncing configuration started'); + this.logService.info('Syncing configuration started'); this.sync(true); return; } else { if (stopIfDisabled) { this.userDataSyncService.stop(); - this.userDataSyncLogService.info('Syncing configuration stopped.'); + this.logService.info('Syncing configuration stopped.'); } } @@ -164,7 +164,14 @@ export class UserDataAutoSync extends Disposable { try { await this.userDataSyncService.sync(); } catch (e) { - this.userDataSyncLogService.error(e); + if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Unauthroized) { + if (e instanceof UserDataSyncStoreError && e.code === UserDataSyncStoreErrorCode.Unauthroized && this.authTokenService.status === AuthTokenStatus.Disabled) { + this.logService.error('Sync failed because the server requires authorization. Please enable authorization.'); + } else { + this.logService.error(e); + } + } + this.logService.error(e); } if (loop) { await timeout(1000 * 5); // Loop sync for every 5s. diff --git a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts index 4c49f62988e..bfcc8fab3cb 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, } from 'vs/base/common/lifecycle'; -import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync'; import { IProductService } from 'vs/platform/product/common/productService'; import { IRequestService, asText, isSuccess } from 'vs/platform/request/common/request'; import { URI } from 'vs/base/common/uri'; @@ -22,7 +22,6 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn constructor( @IProductService private readonly productService: IProductService, @IRequestService private readonly requestService: IRequestService, - @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, @IAuthTokenService private readonly authTokenService: IAuthTokenService, ) { super(); @@ -100,10 +99,11 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn const context = await this.requestService.request(options, token); if (context.res.statusCode === 401) { - // Not Authorized - this.logService.info('Authroization Failed.'); - this.authTokenService.refreshToken(); - Promise.reject('Authroization Failed.'); + if (this.authTokenService.status !== AuthTokenStatus.Disabled) { + this.authTokenService.refreshToken(); + } + // Throw Unauthorized Error + throw new UserDataSyncStoreError('Unauthorized', UserDataSyncStoreErrorCode.Unauthroized); } return context; From ca8a10ba8c02b1f9c760f0cc0e874d7626c051a7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 11:08:40 +0200 Subject: [PATCH 080/435] fix #80754 --- .../contrib/referenceSearch/referencesWidget.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts index 627902b09b9..38f2d1151db 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts @@ -366,21 +366,6 @@ export class ReferenceWidget extends PeekViewWidget { this._tree.onDidChangeFocus(e => { onEvent(e.elements[0], 'show'); }); - this._tree.onDidChangeSelection(e => { - let aside = false; - let goto = false; - if (e.browserEvent instanceof KeyboardEvent) { - // todo@joh make this a command - goto = true; - } - if (aside) { - onEvent(e.elements[0], 'side'); - } else if (goto) { - onEvent(e.elements[0], 'goto'); - } else { - onEvent(e.elements[0], 'show'); - } - }); this._tree.onDidOpen(e => { const aside = (e.browserEvent instanceof MouseEvent) && (e.browserEvent.ctrlKey || e.browserEvent.metaKey || e.browserEvent.altKey); let goto = !e.browserEvent || ((e.browserEvent instanceof MouseEvent) && e.browserEvent.detail === 2); From 1f70a463088a15a0c0575b8985854efab178a794 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Oct 2019 11:57:58 +0200 Subject: [PATCH 081/435] fixes #81715 --- .../debug/browser/breakpointEditorContribution.ts | 15 +++++++++++++++ .../debug/browser/media/debug.contribution.css | 5 +---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 80306bf6af8..d2917d2c74f 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -30,6 +30,7 @@ import { memoize } from 'vs/base/common/decorators'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { distinct } from 'vs/base/common/arrays'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { EditorOption } from 'vs/editor/common/config/editorOptions'; const $ = dom.$; @@ -542,6 +543,20 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable { onHide: () => dispose(actions) }); })); + + const updateSize = () => { + const lineHeight = this.editor.getOption(EditorOption.lineHeight); + this.domNode.style.height = `${lineHeight}px`; + this.domNode.style.width = `${Math.ceil(0.8 * lineHeight)}px`; + this.domNode.style.marginLeft = `${Math.ceil(0.35 * lineHeight)}px`; + }; + updateSize(); + + this.toDispose.push(this.editor.onDidChangeConfiguration(c => { + if (c.hasChanged(EditorOption.fontSize) || c.hasChanged(EditorOption.lineHeight)) { + updateSize(); + } + })); } @memoize diff --git a/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css b/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css index 7bb29ce694b..ca447ebd6d5 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css @@ -50,7 +50,7 @@ .monaco-editor .debug-breakpoint-placeholder::before, .monaco-editor .debug-top-stack-frame-column::before { content: " "; - width: 1.3em; + width: 0.9em; display: inline-block; vertical-align: text-bottom; margin-right: 2px; @@ -62,9 +62,6 @@ } .monaco-editor .inline-breakpoint-widget { - width: 1.3em; - height: 1.3em; - margin-left: 0.61em; cursor: pointer; } From ddcdb9dd6679aaa02c46615130ea5e615e573850 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 2 Oct 2019 12:14:01 +0200 Subject: [PATCH 082/435] json: provideFormatter fix --- .../json-language-features/server/src/jsonServerMain.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/json-language-features/server/src/jsonServerMain.ts b/extensions/json-language-features/server/src/jsonServerMain.ts index 74561395ce8..2439da72e0d 100644 --- a/extensions/json-language-features/server/src/jsonServerMain.ts +++ b/extensions/json-language-features/server/src/jsonServerMain.ts @@ -144,7 +144,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false); - dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (params.initializationOptions.provideFormatter === undefined); + dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (typeof params.initializationOptions.provideFormatter !== 'boolean'); foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); hierarchicalDocumentSymbolSupport = getClientCapability('textDocument.documentSymbol.hierarchicalDocumentSymbolSupport', false); const capabilities: ServerCapabilities = { @@ -153,11 +153,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : undefined, hoverProvider: true, documentSymbolProvider: true, - documentRangeFormattingProvider: false, + documentRangeFormattingProvider: params.initializationOptions.provideFormatter === true, colorProvider: {}, foldingRangeProvider: true, - selectionRangeProvider: true, - documentFormattingProvider: params.initializationOptions.provideFormatter === true + selectionRangeProvider: true }; return { capabilities }; From 46043d41c8bfc319371fa4d336e6ffc7dded95cb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 12:24:52 +0200 Subject: [PATCH 083/435] continue to suppor legacy parameter hints config, #81256 --- src/vs/editor/common/config/editorOptions.ts | 23 +++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index f4c6c2df7f9..7efb1b48869 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1871,14 +1871,25 @@ class EditorParameterHints extends BaseEditorOption Date: Wed, 2 Oct 2019 12:28:48 +0200 Subject: [PATCH 084/435] fix vscode.open() tests (#81833) --- .../src/singlefolder-tests/commands.test.ts | 16 ++++++++-------- scripts/test-integration.bat | 1 + scripts/test-integration.sh | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index 7b2562ce51d..998cfec6168 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -104,13 +104,13 @@ suite('commands namespace tests', () => { return Promise.all([a, b, c, d, e]); }); - // test('api-command: vscode.open', function () { - // let uri = Uri.parse(workspace.workspaceFolders![0].uri.toString() + '/image.png'); - // let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false)); - // let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false)); - // let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true)); - // let d = commands.executeCommand('vscode.open', uri, true).then(() => assert.ok(false), () => assert.ok(true)); + test('api-command: vscode.open', function () { + let uri = Uri.parse(workspace.workspaceFolders![0].uri.toString() + '/image.png'); + let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false)); + let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false)); + let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true)); + let d = commands.executeCommand('vscode.open', uri, true).then(() => assert.ok(false), () => assert.ok(true)); - // return Promise.all([a, b, c, d]); - // }); + return Promise.all([a, b, c, d]); + }); }); diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index d557a24edaa..87773488204 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -20,6 +20,7 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" ( call yarn gulp compile-extension:css-language-features-server call yarn gulp compile-extension:html-language-features-server call yarn gulp compile-extension:json-language-features-server + call yarn gulp compile-extension:image-preview echo "Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build." ) diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index df6219221b7..a695f774361 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -29,6 +29,7 @@ else yarn gulp compile-extension:css-language-features-server yarn gulp compile-extension:html-language-features-server yarn gulp compile-extension:json-language-features-server + yarn gulp compile-extension:image-preview echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build." fi From 2f28b4074ad2e9568cf58d131ce7b9b47cac597e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 12:26:25 +0200 Subject: [PATCH 085/435] Revert "continue to suppor legacy parameter hints config, #81256" This reverts commit 46043d41c8bfc319371fa4d336e6ffc7dded95cb. --- src/vs/editor/common/config/editorOptions.ts | 23 +++++--------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 7efb1b48869..f4c6c2df7f9 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1871,25 +1871,14 @@ class EditorParameterHints extends BaseEditorOption Date: Wed, 2 Oct 2019 12:29:10 +0200 Subject: [PATCH 086/435] migrate parameter hints setting, #81256 --- src/vs/editor/common/config/commonEditorConfig.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index af4f2074ea8..1ec61ff9751 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -207,6 +207,17 @@ function migrateOptions(options: IEditorOptions): void { enabled: false }; } + + const parameterHints = options.parameterHints; + if (parameterHints === true) { + options.parameterHints = { + enabled: true + }; + } else if (parameterHints === false) { + options.parameterHints = { + enabled: false + }; + } } function deepCloneAndMigrateOptions(_options: IEditorOptions): IEditorOptions { From 741323bbb7b2693c857b093e8afa8bae481fe3af Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 12:41:17 +0200 Subject: [PATCH 087/435] fix #81323 --- .../contrib/outline/browser/outlinePanel.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index 9ee2c27c02d..663ecfa53fb 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -249,8 +249,6 @@ export class OutlinePanel extends ViewletPanel { private _treeComparator!: OutlineItemComparator; private _treeStates = new LRUCache(10); - private _treeFakeUIEvent = new UIEvent('me'); - private readonly _contextKeyFocused: IContextKey; private readonly _contextKeyFiltered: IContextKey; @@ -531,10 +529,8 @@ export class OutlinePanel extends ViewletPanel { // feature: reveal outline selection in editor // on change -> reveal/select defining range - this._editorDisposables.add(this._tree.onDidChangeSelection(e => { - if (e.browserEvent === this._treeFakeUIEvent /* || e.payload && e.payload.didClickOnTwistie */) { - return; - } + this._editorDisposables.add(this._tree.onDidOpen(e => { + let [first] = e.elements; if (!(first instanceof OutlineElement)) { return; @@ -636,7 +632,7 @@ export class OutlinePanel extends ViewletPanel { if (top === null) { this._tree.reveal(item, 0.5); } - this._tree.setFocus([item], this._treeFakeUIEvent); - this._tree.setSelection([item], this._treeFakeUIEvent); + this._tree.setFocus([item]); + this._tree.setSelection([item]); } } From 689e2fd320846e69cd25b8d5aec670883cce260f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 2 Oct 2019 14:20:32 +0200 Subject: [PATCH 088/435] fix compile --- .../vscode-api-tests/src/singlefolder-tests/commands.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index 998cfec6168..fba9348435c 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -6,7 +6,7 @@ import 'mocha'; import * as assert from 'assert'; import { join } from 'path'; -import { commands, workspace, window, Uri, Range, Position } from 'vscode'; +import { commands, workspace, window, Uri, Range, Position, ViewColumn } from 'vscode'; suite('commands namespace tests', () => { From 888f86f1568f2e76eeb05d456222837ba7a82d96 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Oct 2019 14:26:09 +0200 Subject: [PATCH 089/435] null guard --- src/vs/workbench/contrib/debug/browser/debugSession.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index b368e7026f8..dcedf0a95e2 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -381,6 +381,10 @@ export class DebugSession implements IDebugSession { if (this.raw) { const source = this.getRawSource(uri); const response = await this.raw.breakpointLocations({ source, line: lineNumber }); + if (!response.body || !response.body.breakpoints) { + return []; + } + const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 })); return distinct(positions, p => `${p.lineNumber}:${p.column}`); From d5ddcf10bfaebf6c20aa44c944de5700e865ddee Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 2 Oct 2019 14:36:30 +0200 Subject: [PATCH 090/435] update gulp-tsb, https://github.com/microsoft/vscode/issues/81140 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4feda2c221a..c215d982d8b 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.4", "gulp-shell": "^0.6.5", - "gulp-tsb": "4.0.4", + "gulp-tsb": "4.0.5", "gulp-tslint": "^8.1.3", "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", diff --git a/yarn.lock b/yarn.lock index a234c0630cb..4304721fc4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3782,10 +3782,10 @@ gulp-symdest@^1.1.1: queue "^3.1.0" vinyl-fs "^2.4.3" -gulp-tsb@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/gulp-tsb/-/gulp-tsb-4.0.4.tgz#c0486534e2f86cd4a11c2393593d9eae3a426ac4" - integrity sha512-BIIls2PpT3+JR1Svvd0SLjkBj2AmlHIRnum/ajf1XQUgbVA9wwsZuTjpVXU/K06KbTYfGsSSYAPRK2dICNAMZQ== +gulp-tsb@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/gulp-tsb/-/gulp-tsb-4.0.5.tgz#2c4b41c5049de374934ca0fdb90dd713638af17a" + integrity sha512-zzjLZZBByrtljBhTbDBsScMVB10TYMXiMUV6FUKogs/hpHyTWdkqtMW/5nDPfsDA1xA+HFLgB19FAgWuPE0ZYw== dependencies: ansi-colors "^1.0.1" fancy-log "^1.3.2" From 57aea60efd0a3ddc577e62c00c36c3046567fe45 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 2 Oct 2019 14:36:53 +0200 Subject: [PATCH 091/435] toggle fold to use cmd+k cmd+l shortcut. Fixes #81795 --- src/vs/editor/contrib/folding/folding.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 6806e903e67..eb550be02fb 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -667,7 +667,7 @@ class ToggleFoldAction extends FoldingAction { precondition: CONTEXT_FOLDING_ENABLED, kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K), + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_L), weight: KeybindingWeight.EditorContrib } }); From c5e2892b29ea55f9bcd85ddc4a72ddb5734b5ba1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 2 Oct 2019 14:38:31 +0200 Subject: [PATCH 092/435] urls - add option to disable confirm dialog --- src/vs/code/electron-main/app.ts | 6 +++--- src/vs/platform/url/common/url.ts | 15 +++++++++++++-- src/vs/platform/url/common/urlIpc.ts | 4 ++-- src/vs/platform/url/common/urlService.ts | 6 +++--- .../workbench/api/browser/mainThreadUrls.ts | 4 ++-- .../browser/extensionsWorkbenchService.ts | 4 ++-- .../contrib/url/common/url.contribution.ts | 2 +- .../extensions/browser/extensionUrlHandler.ts | 19 +++++++++++-------- .../services/url/browser/urlService.ts | 2 +- .../url/electron-browser/urlService.ts | 15 ++++++++++----- 10 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index dd200cde511..073b3587f81 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -24,7 +24,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IURLService } from 'vs/platform/url/common/url'; +import { IURLService, IOpenURLOptions } from 'vs/platform/url/common/url'; import { URLHandlerChannelClient, URLHandlerRouter } from 'vs/platform/url/common/urlIpc'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils'; @@ -588,7 +588,7 @@ export class CodeApplication extends Disposable { // Create a URL handler to open file URIs in the active window const environmentService = accessor.get(IEnvironmentService); urlService.registerHandler({ - async handleURL(uri: URI): Promise { + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { // Catch file URLs if (uri.authority === Schemas.file && !!uri.path) { @@ -615,7 +615,7 @@ export class CodeApplication extends Disposable { // if there is none if (isMacintosh) { urlService.registerHandler({ - async handleURL(uri: URI): Promise { + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { if (windowsMainService.getWindowCount() === 0) { const cli = { ...environmentService.args }; const [window] = windowsMainService.open({ context: OpenContext.API, cli, forceEmpty: true, gotoLineMode: true }); diff --git a/src/vs/platform/url/common/url.ts b/src/vs/platform/url/common/url.ts index 479bc0bca73..097a2398e9b 100644 --- a/src/vs/platform/url/common/url.ts +++ b/src/vs/platform/url/common/url.ts @@ -9,8 +9,19 @@ import { IDisposable } from 'vs/base/common/lifecycle'; export const IURLService = createDecorator('urlService'); +export interface IOpenURLOptions { + + /** + * If not provided or `false`, signals that the + * URL to open did not originate from the product + * but outside. As such, a confirmation dialog + * might be shown to the user. + */ + trusted?: boolean; +} + export interface IURLHandler { - handleURL(uri: URI): Promise; + handleURL(uri: URI, options?: IOpenURLOptions): Promise; } export interface IURLService { @@ -24,7 +35,7 @@ export interface IURLService { */ create(options?: Partial): URI; - open(url: URI): Promise; + open(url: URI, options?: IOpenURLOptions): Promise; registerHandler(handler: IURLHandler): IDisposable; } diff --git a/src/vs/platform/url/common/urlIpc.ts b/src/vs/platform/url/common/urlIpc.ts index 84396c2400e..88a3d20e1d0 100644 --- a/src/vs/platform/url/common/urlIpc.ts +++ b/src/vs/platform/url/common/urlIpc.ts @@ -6,7 +6,7 @@ import { IChannel, IServerChannel, IClientRouter, IConnectionHub, Client } from 'vs/base/parts/ipc/common/ipc'; import { URI } from 'vs/base/common/uri'; import { Event } from 'vs/base/common/event'; -import { IURLHandler } from 'vs/platform/url/common/url'; +import { IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url'; import { CancellationToken } from 'vs/base/common/cancellation'; import { first } from 'vs/base/common/arrays'; @@ -31,7 +31,7 @@ export class URLHandlerChannelClient implements IURLHandler { constructor(private channel: IChannel) { } - handleURL(uri: URI): Promise { + handleURL(uri: URI, options?: IOpenURLOptions): Promise { return this.channel.call('handleURL', uri.toJSON()); } } diff --git a/src/vs/platform/url/common/urlService.ts b/src/vs/platform/url/common/urlService.ts index 322929c723d..030d52b587e 100644 --- a/src/vs/platform/url/common/urlService.ts +++ b/src/vs/platform/url/common/urlService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url'; import { URI, UriComponents } from 'vs/base/common/uri'; import { values } from 'vs/base/common/map'; import { first } from 'vs/base/common/async'; @@ -17,9 +17,9 @@ export abstract class AbstractURLService extends Disposable implements IURLServi abstract create(options?: Partial): URI; - open(uri: URI): Promise { + open(uri: URI, options?: IOpenURLOptions): Promise { const handlers = values(this.handlers); - return first(handlers.map(h => () => h.handleURL(uri)), undefined, false).then(val => val || false); + return first(handlers.map(h => () => h.handleURL(uri, options)), undefined, false).then(val => val || false); } registerHandler(handler: IURLHandler): IDisposable { diff --git a/src/vs/workbench/api/browser/mainThreadUrls.ts b/src/vs/workbench/api/browser/mainThreadUrls.ts index c5f54274e72..a89f291d6c2 100644 --- a/src/vs/workbench/api/browser/mainThreadUrls.ts +++ b/src/vs/workbench/api/browser/mainThreadUrls.ts @@ -5,7 +5,7 @@ import { ExtHostContext, IExtHostContext, MainContext, MainThreadUrlsShape, ExtHostUrlsShape } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer } from '../common/extHostCustomers'; -import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IExtensionUrlHandler } from 'vs/workbench/services/extensions/browser/extensionUrlHandler'; @@ -19,7 +19,7 @@ class ExtensionUrlHandler implements IURLHandler { readonly extensionId: ExtensionIdentifier ) { } - handleURL(uri: URI): Promise { + handleURL(uri: URI, options?: IOpenURLOptions): Promise { if (!ExtensionIdentifier.equals(this.extensionId, uri.authority)) { return Promise.resolve(false); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 087dd63f6f8..2f7add6821a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -24,7 +24,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { URI } from 'vs/base/common/uri'; import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; @@ -1048,7 +1048,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension this.notificationService.error(err); } - handleURL(uri: URI): Promise { + handleURL(uri: URI, options?: IOpenURLOptions): Promise { if (!/^extension/.test(uri.path)) { return Promise.resolve(false); } diff --git a/src/vs/workbench/contrib/url/common/url.contribution.ts b/src/vs/workbench/contrib/url/common/url.contribution.ts index 4ba68ecd95b..10c3edf2150 100644 --- a/src/vs/workbench/contrib/url/common/url.contribution.ts +++ b/src/vs/workbench/contrib/url/common/url.contribution.ts @@ -35,7 +35,7 @@ export class OpenUrlAction extends Action { run(): Promise { return this.quickInputService.input({ prompt: 'URL to open' }).then(input => { const uri = URI.parse(input); - this.urlService.open(uri); + this.urlService.open(uri, { trusted: true }); }); } } diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index c969bd3df55..62d36c968e1 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -15,7 +15,7 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IURLHandler, IURLService } from 'vs/platform/url/common/url'; +import { IURLHandler, IURLService, IOpenURLOptions } from 'vs/platform/url/common/url'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; @@ -74,7 +74,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { const urlToHandleValue = this.storageService.get(URL_TO_HANDLE, StorageScope.WORKSPACE); if (urlToHandleValue) { this.storageService.remove(URL_TO_HANDLE, StorageScope.WORKSPACE); - this.handleURL(URI.revive(JSON.parse(urlToHandleValue)), true); + this.handleURL(URI.revive(JSON.parse(urlToHandleValue)), { trusted: true }); } this.disposable = combinedDisposable( @@ -86,7 +86,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { setTimeout(() => cache.forEach(uri => this.handleURL(uri))); } - async handleURL(uri: URI, confirmed?: boolean): Promise { + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { if (!isExtensionId(uri.authority)) { return false; } @@ -100,12 +100,15 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { return true; } - if (!confirmed) { + let showConfirm: boolean; + if (options && options.trusted) { + showConfirm = false; + } else { const confirmedExtensionIds = this.getConfirmedExtensionIds(); - confirmed = confirmedExtensionIds.has(ExtensionIdentifier.toKey(extensionId)); + showConfirm = !confirmedExtensionIds.has(ExtensionIdentifier.toKey(extensionId)); } - if (!confirmed) { + if (showConfirm) { let uriString = uri.toString(); if (uriString.length > 40) { @@ -136,7 +139,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { if (handler) { if (!wasHandlerAvailable) { // forward it directly - return await handler.handleURL(uri); + return await handler.handleURL(uri, options); } // let the ExtensionUrlHandler instance handle this @@ -343,7 +346,7 @@ class ExtensionUrlBootstrapHandler implements IWorkbenchContribution, IURLHandle ExtensionUrlBootstrapHandler.disposable = urlService.registerHandler(this); } - handleURL(uri: URI): Promise { + handleURL(uri: URI, options?: IOpenURLOptions): Promise { ExtensionUrlBootstrapHandler._cache.push(uri); return Promise.resolve(true); } diff --git a/src/vs/workbench/services/url/browser/urlService.ts b/src/vs/workbench/services/url/browser/urlService.ts index b073447fc26..eef5070c450 100644 --- a/src/vs/workbench/services/url/browser/urlService.ts +++ b/src/vs/workbench/services/url/browser/urlService.ts @@ -54,7 +54,7 @@ export class BrowserURLService extends AbstractURLService { private registerListeners(): void { if (this.provider) { - this._register(this.provider.onCallback(uri => this.open(uri))); + this._register(this.provider.onCallback(uri => this.open(uri, { trusted: true }))); } } diff --git a/src/vs/workbench/services/url/electron-browser/urlService.ts b/src/vs/workbench/services/url/electron-browser/urlService.ts index 319de3fbd12..73fa15e1f8e 100644 --- a/src/vs/workbench/services/url/electron-browser/urlService.ts +++ b/src/vs/workbench/services/url/electron-browser/urlService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; import { URLHandlerChannel } from 'vs/platform/url/common/urlIpc'; @@ -15,6 +15,11 @@ import { IElectronEnvironmentService } from 'vs/workbench/services/electron/elec import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; import { IElectronService } from 'vs/platform/electron/node/electron'; +export interface IRelayOpenURLOptions extends IOpenURLOptions { + openToSide?: boolean; + openExternal?: boolean; +} + export class RelayURLService extends URLService implements IURLHandler { private urlService: IURLService; @@ -46,16 +51,16 @@ export class RelayURLService extends URLService implements IURLHandler { return uri.with({ query }); } - async open(resource: URI, options?: { openToSide?: boolean, openExternal?: boolean }): Promise { + async open(resource: URI, options?: IRelayOpenURLOptions): Promise { if (resource.scheme !== product.urlProtocol) { return false; } - return await this.urlService.open(resource); + return await this.urlService.open(resource, options); } - async handleURL(uri: URI): Promise { - const result = await super.open(uri); + async handleURL(uri: URI, options?: IOpenURLOptions): Promise { + const result = await super.open(uri, options); if (result) { await this.electronService.focusWindow(); From d09090927edce61db334f2ced13bd3d916a87add Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 14:52:07 +0200 Subject: [PATCH 093/435] fixes #81731 --- src/vs/workbench/contrib/scm/browser/media/scmViewlet.css | 4 ++++ src/vs/workbench/contrib/scm/browser/repositoryPanel.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css index f8d0d427d53..3a9e2683996 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css +++ b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css @@ -170,3 +170,7 @@ width: 8px !important; margin-right: 0 !important; } + +.scm-viewlet .scm-status.show-file-icons.hide-arrows.tree-view-mode .monaco-tl-indent .indent-guide:first-child { + border: none; +} diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index 36cc3b7d8d2..db634534373 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -703,6 +703,7 @@ export class RepositoryPanel extends ViewletPanel { const updateIndentStyles = (theme: IFileIconTheme) => { toggleClass(this.listContainer, 'list-view-mode', this.viewModel.mode === ViewModelMode.List); + toggleClass(this.listContainer, 'tree-view-mode', this.viewModel.mode === ViewModelMode.Tree); toggleClass(this.listContainer, 'align-icons-and-twisties', this.viewModel.mode === ViewModelMode.Tree && theme.hasFileIcons && !theme.hasFolderIcons); toggleClass(this.listContainer, 'hide-arrows', this.viewModel.mode === ViewModelMode.Tree && theme.hidesExplorerArrows === true); }; From f52667b2493a71919b5765037d0eb05dfcf1400a Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 2 Oct 2019 15:22:31 +0200 Subject: [PATCH 094/435] Add to jsdoc for TreeView message Add info about how to remove the message Fiexes #81758 --- src/vs/vscode.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 8ea0f29d743..0c986857ad6 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -7016,6 +7016,7 @@ declare module 'vscode' { /** * An optional human-readable message that will be rendered in the view. + * Setting the message to null, undefined, or empty string will remove the message from the view. */ message?: string; From a8fc2bd9be2339fff59c9325a350d73ed470c95f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 2 Oct 2019 15:12:46 +0200 Subject: [PATCH 095/435] fix #81763 --- .../dialogs/electron-browser/dialogService.ts | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts index 3c564000389..43caf27af2e 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts @@ -43,10 +43,11 @@ export class DialogService implements IDialogService { _serviceBrand: undefined; - private impl: IDialogService; + private nativeImpl: IDialogService; + private customImpl: IDialogService; constructor( - @IConfigurationService configurationService: IConfigurationService, + @IConfigurationService private configurationService: IConfigurationService, @ILogService logService: ILogService, @ILayoutService layoutService: ILayoutService, @IThemeService themeService: IThemeService, @@ -56,27 +57,32 @@ export class DialogService implements IDialogService { @IClipboardService clipboardService: IClipboardService, @IElectronService electronService: IElectronService ) { + this.customImpl = new HTMLDialogService(logService, layoutService, themeService, keybindingService, productService, clipboardService); + this.nativeImpl = new NativeDialogService(logService, sharedProcessService, electronService, clipboardService); + } - // Use HTML based dialogs - if (configurationService.getValue('workbench.dialogs.customEnabled') === true) { - this.impl = new HTMLDialogService(logService, layoutService, themeService, keybindingService, productService, clipboardService); - } - // Electron dialog service - else { - this.impl = new NativeDialogService(logService, sharedProcessService, electronService, clipboardService); - } + private get useCustomDialog(): boolean { + return this.configurationService.getValue('workbench.dialogs.customEnabled') === true; } confirm(confirmation: IConfirmation): Promise { - return this.impl.confirm(confirmation); + if (this.useCustomDialog) { + return this.customImpl.confirm(confirmation); + } + + return this.nativeImpl.confirm(confirmation); } show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions | undefined): Promise { - return this.impl.show(severity, message, buttons, options); + if (this.useCustomDialog) { + return this.customImpl.show(severity, message, buttons, options); + } + + return this.nativeImpl.show(severity, message, buttons, options); } about(): Promise { - return this.impl.about(); + return this.nativeImpl.about(); } } From c850f0716e6193d0a11d48c81b29c8aff6147d1b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 15:30:21 +0200 Subject: [PATCH 096/435] fixes #81798 --- src/vs/base/common/map.ts | 4 +++- src/vs/base/common/resourceTree.ts | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 007d0a0d529..dadb16862bb 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -117,6 +117,8 @@ export class PathIterator implements IKeyIterator { private _from!: number; private _to!: number; + constructor(private _splitOnBackslash: boolean = true) { } + reset(key: string): this { this._value = key.replace(/\\$|\/$/, ''); this._from = 0; @@ -134,7 +136,7 @@ export class PathIterator implements IKeyIterator { let justSeps = true; for (; this._to < this._value.length; this._to++) { const ch = this._value.charCodeAt(this._to); - if (ch === CharCode.Slash || ch === CharCode.Backslash) { + if (ch === CharCode.Slash || this._splitOnBackslash && ch === CharCode.Backslash) { if (justSeps) { this._from++; } else { diff --git a/src/vs/base/common/resourceTree.ts b/src/vs/base/common/resourceTree.ts index 98c0f518d73..f11e02c42b5 100644 --- a/src/vs/base/common/resourceTree.ts +++ b/src/vs/base/common/resourceTree.ts @@ -9,6 +9,7 @@ import { Iterator } from 'vs/base/common/iterator'; import { relativePath, joinPath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { mapValues } from 'vs/base/common/collections'; +import { PathIterator } from 'vs/base/common/map'; export interface ILeafNode { readonly uri: URI; @@ -113,18 +114,18 @@ export class ResourceTree, C> { add(uri: URI, element: T): void { const key = relativePath(this.root.uri, uri) || uri.fsPath; - const parts = key.split(/[\\\/]/).filter(p => !!p); + const iterator = new PathIterator(false).reset(key); let node = this.root; let path = ''; - for (let i = 0; i < parts.length; i++) { - const name = parts[i]; + while (true) { + const name = iterator.value(); path = path + '/' + name; let child = node.get(name); if (!child) { - if (i < parts.length - 1) { + if (iterator.hasNext()) { child = new BranchNode(joinPath(this.root.uri, path), path, this.root.context, node); node.set(name, child); } else { @@ -135,18 +136,24 @@ export class ResourceTree, C> { } if (!(child instanceof BranchNode)) { - if (i < parts.length - 1) { + if (iterator.hasNext()) { throw new Error('Inconsistent tree: can\'t override leaf with branch.'); } // replace node.set(name, new LeafNode(uri, path, this.root.context, element)); return; - } else if (i === parts.length - 1) { + } else if (!iterator.hasNext()) { throw new Error('Inconsistent tree: can\'t override branch with leaf.'); } node = child; + + if (!iterator.hasNext()) { + return; + } + + iterator.next(); } } From 1d8037c63c3b431cc77ecc635dcbc2c485b21e40 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 2 Oct 2019 15:36:09 +0200 Subject: [PATCH 097/435] Update default build task placeholder text for defaultBuildTask variable Fixes https://github.com/microsoft/vscode/issues/81817 --- src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 24306cab559..23fbb2cbd15 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -290,7 +290,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer let entry: TaskQuickPickEntry | null | undefined; if (tasks && tasks.length > 0) { - entry = await this.showQuickPick(tasks, nls.localize('TaskService.pickBuildTaskForLabel', 'Select the build task')); + entry = await this.showQuickPick(tasks, nls.localize('TaskService.pickBuildTaskForLabel', 'Select the build task (there is no default build task defined)')); } let task: Task | undefined | null = entry ? entry.task : undefined; From 75e6fa0797aa7cdcb80653393dc5d8021c5390d7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 2 Oct 2019 15:42:16 +0200 Subject: [PATCH 098/435] Add completion suggestion for defaultBuildTask Fixes #81816 --- extensions/configuration-editing/src/extension.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/configuration-editing/src/extension.ts b/extensions/configuration-editing/src/extension.ts index aff533d86d9..72e2fcf627f 100644 --- a/extensions/configuration-editing/src/extension.ts +++ b/extensions/configuration-editing/src/extension.ts @@ -75,7 +75,8 @@ function registerVariableCompletions(pattern: string): vscode.Disposable { { label: 'fileDirname', detail: localize('fileDirname', "The current opened file's dirname") }, { label: 'fileExtname', detail: localize('fileExtname', "The current opened file's extension") }, { label: 'fileBasename', detail: localize('fileBasename', "The current opened file's basename") }, - { label: 'fileBasenameNoExtension', detail: localize('fileBasenameNoExtension', "The current opened file's basename with no file extension") } + { label: 'fileBasenameNoExtension', detail: localize('fileBasenameNoExtension', "The current opened file's basename with no file extension") }, + { label: 'defaultBuildTask', detail: localize('defaultBuildTask', "The name of the default build task. If there is not a single default build task then a quick pick is shown to choose the build task.") }, ].map(variable => ({ label: '${' + variable.label + '}', range: new vscode.Range(startPosition, position), From fb10f85b4c20038c2634c368d2c2d57d08d756ce Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 2 Oct 2019 15:45:03 +0200 Subject: [PATCH 099/435] fix #81653 --- .../electron/electron-main/electronMainService.ts | 4 ++-- src/vs/platform/electron/node/electron.ts | 2 +- .../workbench/electron-browser/actions/windowActions.ts | 8 ++++---- src/vs/workbench/electron-browser/desktop.contribution.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 71581fd6bbd..85bc12ccaf5 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -283,10 +283,10 @@ export class ElectronMainService implements AddFirstParameterToFunctions { + async reload(windowId: number, options?: { disableExtensions?: boolean }): Promise { const window = this.windowsMainService.getWindowById(windowId); if (window) { - return this.windowsMainService.reload(window); + return this.windowsMainService.reload(window, options && options.disableExtensions ? { _: [], 'disable-extensions': true } : undefined); } } diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/node/electron.ts index 1454542c92b..abb83c18f0d 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/node/electron.ts @@ -75,7 +75,7 @@ export interface IElectronService { // Lifecycle relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): Promise; - reload(): Promise; + reload(options?: { disableExtensions?: boolean }): Promise; closeWorkspace(): Promise; closeWindow(): Promise; quit(): Promise; diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-browser/actions/windowActions.ts index 9e82222446e..2efe92ef881 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-browser/actions/windowActions.ts @@ -137,10 +137,10 @@ export class ZoomResetAction extends BaseZoomAction { } } -export class RestartWithExtensionsDisabledAction extends Action { +export class ReloadWindowWithExtensionsDisabledAction extends Action { - static readonly ID = 'workbench.action.restartWithExtensionsDisabled'; - static LABEL = nls.localize('restartWithExtensionsDisabled', "Restart With Extensions Disabled"); + static readonly ID = 'workbench.action.reloadWindowWithExtensionsDisabled'; + static LABEL = nls.localize('reloadWindowWithExtensionsDisabled', "Reload With Extensions Disabled"); constructor( id: string, @@ -151,7 +151,7 @@ export class RestartWithExtensionsDisabledAction extends Action { } async run(): Promise { - await this.electronService.relaunch({ addArgs: ['--disable-extensions'] }); + await this.electronService.reload({ disableExtensions: true }); return true; } diff --git a/src/vs/workbench/electron-browser/desktop.contribution.ts b/src/vs/workbench/electron-browser/desktop.contribution.ts index 94a1259ed28..b50b169627c 100644 --- a/src/vs/workbench/electron-browser/desktop.contribution.ts +++ b/src/vs/workbench/electron-browser/desktop.contribution.ts @@ -12,7 +12,7 @@ import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/action import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; import { ToggleSharedProcessAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions'; -import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, RestartWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions'; +import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions'; import { SaveWorkspaceAsAction, DuplicateWorkspaceInNewWindowAction } from 'vs/workbench/electron-browser/actions/workspaceActions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -98,7 +98,7 @@ import { IElectronService } from 'vs/platform/electron/node/electron'; (function registerDeveloperActions(): void { const developerCategory = nls.localize('developer', "Developer"); registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSharedProcessAction, ToggleSharedProcessAction.ID, ToggleSharedProcessAction.LABEL), 'Developer: Toggle Shared Process', developerCategory); - registry.registerWorkbenchAction(new SyncActionDescriptor(RestartWithExtensionsDisabledAction, RestartWithExtensionsDisabledAction.ID, RestartWithExtensionsDisabledAction.LABEL), 'Developer: Restart With Extensions Disabled', developerCategory); + registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Developer: Reload With Extensions Disabled', developerCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL), 'Developer: Toggle Developer Tools', developerCategory); KeybindingsRegistry.registerKeybindingRule({ From a8a448d166f66bcedcab350858b959a07b9bdfdb Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Oct 2019 15:55:10 +0200 Subject: [PATCH 100/435] fixes #77837 --- src/vs/workbench/contrib/debug/browser/repl.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 3935ae45643..ea0f700bb49 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -80,7 +80,7 @@ interface IPrivateReplService { } function revealLastElement(tree: WorkbenchAsyncDataTree) { - tree.scrollTop = tree.scrollHeight - tree.renderHeight; + tree.scrollTop = Number.POSITIVE_INFINITY; } const sessionsToIgnore = new Set(); @@ -799,8 +799,6 @@ class ReplDelegate implements IListVirtualDelegate { constructor(private configurationService: IConfigurationService) { } getHeight(element: IReplElement): number { - const countNumberOfLines = (str: string) => Math.max(1, (str && str.match(/\r\n|\n/g) || []).length); - // Give approximate heights. Repl has dynamic height so the tree will measure the actual height on its own. const config = this.configurationService.getValue('debug'); const fontSize = config.console.fontSize; @@ -819,13 +817,13 @@ class ReplDelegate implements IListVirtualDelegate { return rowHeight; } - let valueRows = value ? (countNumberOfLines(value) + Math.floor(value.length / 150)) : 0; + let valueRows = value ? Math.ceil(value.length / 150) : 0; return rowHeight * valueRows; } if (element instanceof SimpleReplElement || element instanceof ReplEvaluationInput) { let value = element.value; - let valueRows = countNumberOfLines(value) + Math.floor(value.length / 150); + let valueRows = Math.ceil(value.length / 150); return valueRows * rowHeight; } From 2f06eb9855421cc74ffdad4a4ff80771eb254e56 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 2 Oct 2019 16:07:52 +0200 Subject: [PATCH 101/435] Fix #79116 --- .../browser/extensionsWorkbenchService.ts | 38 ++++---- .../extensionsWorkbenchService.test.ts | 40 ++++++++ .../common/extensionEnablementService.ts | 13 +-- .../extensionEnablementService.test.ts | 91 +------------------ 4 files changed, 60 insertions(+), 122 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 2f7add6821a..c78938f30cc 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -14,7 +14,7 @@ import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, - InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IExtensionIdentifier + InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IExtensionIdentifier, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet, groupByExtension, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -308,8 +308,8 @@ ${this.description} class Extensions extends Disposable { - private readonly _onChange: Emitter = new Emitter(); - get onChange(): Event { return this._onChange.event; } + private readonly _onChange: Emitter<{ extension: Extension, operation?: InstallOperation } | undefined> = this._register(new Emitter<{ extension: Extension, operation?: InstallOperation } | undefined>()); + get onChange(): Event<{ extension: Extension, operation?: InstallOperation } | undefined> { return this._onChange.event; } private installing: Extension[] = []; private uninstalling: Extension[] = []; @@ -370,7 +370,7 @@ class Extensions extends Disposable { const local = extension.local.metadata ? extension.local : await this.server.extensionManagementService.updateMetadata(extension.local, { id: compatible.identifier.uuid, publisherDisplayName: compatible.publisherDisplayName, publisherId: compatible.publisherId }); extension.local = local; extension.gallery = compatible; - this._onChange.fire(extension); + this._onChange.fire({ extension }); return true; } return false; @@ -397,7 +397,7 @@ class Extensions extends Disposable { const extension = this.installed.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0] || this.instantiationService.createInstance(Extension, this.stateProvider, this.server, undefined, gallery); this.installing.push(extension); - this._onChange.fire(extension); + this._onChange.fire({ extension }); } } @@ -421,9 +421,10 @@ class Extensions extends Disposable { if (!extension.gallery) { extension.gallery = gallery; } + extension.enablementState = this.extensionEnablementService.getEnablementState(local); } } - this._onChange.fire(error ? undefined : extension); + this._onChange.fire(error || !extension ? undefined : { extension, operation: event.operation }); } private onUninstallExtension(identifier: IExtensionIdentifier): void { @@ -431,7 +432,7 @@ class Extensions extends Disposable { if (extension) { const uninstalling = this.uninstalling.filter(e => areSameExtensions(e.identifier, identifier))[0] || extension; this.uninstalling = [uninstalling, ...this.uninstalling.filter(e => !areSameExtensions(e.identifier, identifier))]; - this._onChange.fire(uninstalling); + this._onChange.fire(uninstalling ? { extension: uninstalling } : undefined); } } @@ -442,7 +443,7 @@ class Extensions extends Disposable { const uninstalling = this.uninstalling.filter(e => areSameExtensions(e.identifier, identifier))[0]; this.uninstalling = this.uninstalling.filter(e => !areSameExtensions(e.identifier, identifier)); if (uninstalling) { - this._onChange.fire(uninstalling); + this._onChange.fire({ extension: uninstalling }); } } @@ -453,7 +454,7 @@ class Extensions extends Disposable { const enablementState = this.extensionEnablementService.getEnablementState(extension.local); if (enablementState !== extension.enablementState) { (extension as Extension).enablementState = enablementState; - this._onChange.fire(extension as Extension); + this._onChange.fire({ extension: extension as Extension }); } } } @@ -506,11 +507,13 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension super(); if (this.extensionManagementServerService.localExtensionManagementServer) { this.localExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.localExtensionManagementServer, ext => this.getExtensionState(ext))); - this._register(this.localExtensions.onChange(e => this._onChange.fire(e))); + this._register(this.localExtensions.onChange(e => this._onChange.fire(e ? e.extension : undefined))); + this._register(Event.filter(this.localExtensions.onChange, e => !!e && e.operation === InstallOperation.Install)(e => this.onDidInstallExtension(e!.extension))); } if (this.extensionManagementServerService.remoteExtensionManagementServer) { this.remoteExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.remoteExtensionManagementServer, ext => this.getExtensionState(ext))); - this._register(this.remoteExtensions.onChange(e => this._onChange.fire(e))); + this._register(this.remoteExtensions.onChange(e => this._onChange.fire(e ? e.extension : undefined))); + this._register(Event.filter(this.remoteExtensions.onChange, e => !!e && e.operation === InstallOperation.Install)(e => this.onDidInstallExtension(e!.extension))); } this.syncDelayer = new ThrottledDelayer(ExtensionsWorkbenchService.SyncPeriod); @@ -784,7 +787,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension if (extension instanceof URI) { return this.installWithProgress(async () => { const { identifier } = await this.extensionService.install(extension); - this.checkAndEnableDisabledDependencies(identifier); return this.local.filter(local => areSameExtensions(local.identifier, identifier))[0]; }); } @@ -801,7 +803,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension return this.installWithProgress(async () => { await this.installFromGallery(extension, gallery); - this.checkAndEnableDisabledDependencies(gallery.identifier); return this.local.filter(local => areSameExtensions(local.identifier, gallery.identifier))[0]; }, gallery.displayName); } @@ -887,15 +888,8 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension } } - private checkAndEnableDisabledDependencies(extensionIdentifier: IExtensionIdentifier): Promise { - const extension = this.local.filter(e => (e.local || e.gallery) && areSameExtensions(extensionIdentifier, e.identifier))[0]; - if (extension) { - const disabledDepencies = this.getExtensionsRecursively([extension], this.local, EnablementState.EnabledGlobally, { dependencies: true, pack: false }); - if (disabledDepencies.length) { - return this.setEnablement(disabledDepencies, EnablementState.EnabledGlobally); - } - } - return Promise.resolve(); + private onDidInstallExtension(extension: IExtension): void { + this.setEnablement(extension, EnablementState.EnabledGlobally); } private promptAndSetEnablement(extensions: IExtension[], enablementState: EnablementState): Promise { diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index fbaac3cc4f9..d3568cdb3af 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -942,6 +942,46 @@ suite('ExtensionsWorkbenchServiceTest', () => { }); }); + test('test installing an extension re-eanbles it when disabled globally', async () => { + testObject = await aWorkbenchService(); + const local = aLocalExtension('pub.a'); + await instantiationService.get(IExtensionEnablementService).setEnablement([local], EnablementState.DisabledGlobally); + didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + const actual = await testObject.queryLocal(); + assert.equal(actual[0].enablementState, EnablementState.EnabledGlobally); + }); + + test('test updating an extension does not re-eanbles it when disabled globally', async () => { + testObject = await aWorkbenchService(); + const local = aLocalExtension('pub.a'); + await instantiationService.get(IExtensionEnablementService).setEnablement([local], EnablementState.DisabledGlobally); + didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + const actual = await testObject.queryLocal(); + assert.equal(actual[0].enablementState, EnablementState.DisabledGlobally); + }); + + test('test installing an extension re-eanbles it when workspace disabled', async () => { + testObject = await aWorkbenchService(); + const local = aLocalExtension('pub.a'); + await instantiationService.get(IExtensionEnablementService).setEnablement([local], EnablementState.DisabledWorkspace); + didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + const actual = await testObject.queryLocal(); + assert.equal(actual[0].enablementState, EnablementState.EnabledGlobally); + }); + + test('test updating an extension does not re-eanbles it when workspace disabled', async () => { + testObject = await aWorkbenchService(); + const local = aLocalExtension('pub.a'); + await instantiationService.get(IExtensionEnablementService).setEnablement([local], EnablementState.DisabledWorkspace); + didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + const actual = await testObject.queryLocal(); + assert.equal(actual[0].enablementState, EnablementState.DisabledWorkspace); + }); + async function aWorkbenchService(): Promise { const workbenchService: ExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService); await workbenchService.queryLocal(); diff --git a/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts index cbed6dcbbd9..8708f30a37c 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionIdentifier, DidInstallExtensionEvent, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionEnablementService, EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; @@ -43,7 +43,6 @@ export class ExtensionEnablementService extends Disposable implements IExtension super(); this.storageManger = this._register(new StorageManager(storageService)); this._register(this.storageManger.onDidChange(extensions => this.onDidChangeStorage(extensions))); - this._register(extensionManagementService.onDidInstallExtension(this._onDidInstallExtension, this)); this._register(extensionManagementService.onDidUninstallExtension(this._onDidUninstallExtension, this)); } @@ -286,16 +285,6 @@ export class ExtensionEnablementService extends Disposable implements IExtension this._onEnablementChanged.fire(extensions); } - private _onDidInstallExtension(event: DidInstallExtensionEvent): void { - if (event.local && event.operation === InstallOperation.Install) { - const wasDisabled = !this.isEnabled(event.local); - this._reset(event.local.identifier); - if (wasDisabled) { - this._onEnablementChanged.fire([event.local]); - } - } - } - private _onDidUninstallExtension({ identifier, error }: DidUninstallExtensionEvent): void { if (!error) { this._reset(identifier); diff --git a/src/vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test.ts b/src/vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test.ts index 88955149380..93bc95313b8 100644 --- a/src/vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test.ts +++ b/src/vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { IExtensionManagementService, DidUninstallExtensionEvent, ILocalExtension, DidInstallExtensionEvent, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, DidUninstallExtensionEvent, ILocalExtension, DidInstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionEnablementService, EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionEnablementService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; @@ -71,12 +71,11 @@ suite('ExtensionEnablementService Test', () => { let testObject: IExtensionEnablementService; const didUninstallEvent = new Emitter(); - const didInstallEvent = new Emitter(); setup(() => { instantiationService = new TestInstantiationService(); instantiationService.stub(IConfigurationService, new TestConfigurationService()); - instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([] as ILocalExtension[]) } as IExtensionManagementService); + instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, getInstalled: () => Promise.resolve([] as ILocalExtension[]) } as IExtensionManagementService); instantiationService.stub(IExtensionManagementServerService, { localExtensionManagementServer: { extensionManagementService: instantiationService.get(IExtensionManagementService) @@ -338,90 +337,6 @@ suite('ExtensionEnablementService Test', () => { assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledGlobally); }); - test('test installing an extension re-eanbles it when disabled globally', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledGlobally); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); - assert.ok(testObject.isEnabled(local)); - assert.equal(testObject.getEnablementState(local), EnablementState.EnabledGlobally); - }); - - test('test updating an extension does not re-eanbles it when disabled globally', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledGlobally); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); - assert.ok(!testObject.isEnabled(local)); - assert.equal(testObject.getEnablementState(local), EnablementState.DisabledGlobally); - }); - - test('test installing an extension fires enablement change event when disabled globally', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledGlobally); - return new Promise((c, e) => { - testObject.onEnablementChanged(([e]) => { - if (e.identifier.id === local.identifier.id) { - c(); - } - }); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); - }); - }); - - test('test updating an extension does not fires enablement change event when disabled globally', async () => { - const target = sinon.spy(); - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledGlobally); - testObject.onEnablementChanged(target); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); - assert.ok(!target.called); - }); - - test('test installing an extension re-eanbles it when workspace disabled', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledWorkspace); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); - assert.ok(testObject.isEnabled(local)); - assert.equal(testObject.getEnablementState(local), EnablementState.EnabledGlobally); - }); - - test('test updating an extension does not re-eanbles it when workspace disabled', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledWorkspace); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); - assert.ok(!testObject.isEnabled(local)); - assert.equal(testObject.getEnablementState(local), EnablementState.DisabledWorkspace); - }); - - test('test installing an extension fires enablement change event when workspace disabled', async () => { - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledWorkspace); - return new Promise((c, e) => { - testObject.onEnablementChanged(([e]) => { - if (e.identifier.id === local.identifier.id) { - c(); - } - }); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); - }); - }); - - test('test updating an extension does not fires enablement change event when workspace disabled', async () => { - const target = sinon.spy(); - const local = aLocalExtension('pub.a'); - await testObject.setEnablement([local], EnablementState.DisabledWorkspace); - testObject.onEnablementChanged(target); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update }); - assert.ok(!target.called); - }); - - test('test installing an extension should not fire enablement change event when extension is not disabled', async () => { - const target = sinon.spy(); - const local = aLocalExtension('pub.a'); - testObject.onEnablementChanged(target); - didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install }); - assert.ok(!target.called); - }); - test('test remove an extension from disablement list when uninstalled', async () => { const extension = aLocalExtension('pub.a'); await testObject.setEnablement([extension], EnablementState.DisabledWorkspace); @@ -480,7 +395,7 @@ suite('ExtensionEnablementService Test', () => { test('test extension is disabled when disabled in enviroment', async () => { const extension = aLocalExtension('pub.a'); instantiationService.stub(IWorkbenchEnvironmentService, { disableExtensions: ['pub.a'] } as IWorkbenchEnvironmentService); - instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([extension, aLocalExtension('pub.b')]) } as IExtensionManagementService); + instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, getInstalled: () => Promise.resolve([extension, aLocalExtension('pub.b')]) } as IExtensionManagementService); testObject = new TestExtensionEnablementService(instantiationService); assert.ok(!testObject.isEnabled(extension)); assert.deepEqual(testObject.getEnablementState(extension), EnablementState.DisabledByEnvironemt); From 1e7a92b119d68a93b0d33bb83b5d4feee4ff984f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 2 Oct 2019 16:14:50 +0200 Subject: [PATCH 102/435] Fix double prompting for default build task when canceled Fixes #81767 --- .../browser/configurationResolverService.ts | 8 ++--- .../common/configurationResolver.ts | 2 +- .../common/variableResolver.ts | 34 ++++++++++--------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index 882b085ff97..680042ebb70 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -91,21 +91,21 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR config = await this.resolveAny(folder, config); // resolve input variables in the order in which they are encountered - return this.resolveWithInteraction(folder, config, section, variables, true).then(mapping => { + return this.resolveWithInteraction(folder, config, section, variables, false).then(mapping => { // finally substitute evaluated command variables (if there are any) if (!mapping) { return null; } else if (mapping.size > 0) { - return this.resolveAny(folder, config, fromMap(mapping)); + return this.resolveAny(folder, config, fromMap(mapping), false); } else { return config; } }); } - public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary, skipContributed: boolean = false): Promise | undefined> { + public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary, resolveContributed: boolean = true): Promise | undefined> { // resolve any non-interactive variables and any contributed variables - const resolved = await this.resolveAnyMap(folder, config); + const resolved = await this.resolveAnyMap(folder, config, resolveContributed); config = resolved.newConfig; const allVariableMapping: Map = resolved.resolvedVariables; diff --git a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts index ea98be3d578..493824af804 100644 --- a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts @@ -20,7 +20,7 @@ export interface IConfigurationResolverService { * Recursively resolves all variables in the given config and returns a copy of it with substituted values. * Command variables are only substituted if a "commandValueMapping" dictionary is given and if it contains an entry for the command. */ - resolveAny(folder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): Promise; + resolveAny(folder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolveContributed?: boolean): Promise; /** * Recursively resolves all variables (including commands and user input) in the given config and returns a copy of it with substituted values. diff --git a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts index 469a3ea58b8..1e75e82e345 100644 --- a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts @@ -53,7 +53,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return this.recursiveResolve(root ? root.uri : undefined, value); } - private async resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { + private async resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { const result = objects.deepClone(config) as any; // hoist platform specific attributes to top level @@ -71,16 +71,16 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe delete result.linux; // substitute all variables recursively in string values - return this.recursiveResolvePromise(workspaceFolder ? workspaceFolder.uri : undefined, result, commandValueMapping, resolvedVariables); + return this.recursiveResolvePromise(workspaceFolder ? workspaceFolder.uri : undefined, result, resolveContributed, commandValueMapping, resolvedVariables); } - public resolveAny(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): Promise { - return this.resolveAnyBase(workspaceFolder, config, commandValueMapping); + public resolveAny(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolveContributed: boolean = true): Promise { + return this.resolveAnyBase(workspaceFolder, config, resolveContributed, commandValueMapping); } - protected async resolveAnyMap(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): Promise<{ newConfig: any, resolvedVariables: Map }> { + protected async resolveAnyMap(workspaceFolder: IWorkspaceFolder | undefined, config: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary): Promise<{ newConfig: any, resolvedVariables: Map }> { const resolvedVariables = new Map(); - const newConfig = await this.resolveAnyBase(workspaceFolder, config, commandValueMapping, resolvedVariables); + const newConfig = await this.resolveAnyBase(workspaceFolder, config, resolveContributed, commandValueMapping, resolvedVariables); return { newConfig, resolvedVariables }; } @@ -116,17 +116,17 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return value; } - private async recursiveResolvePromise(folderUri: uri | undefined, value: any, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { + private async recursiveResolvePromise(folderUri: uri | undefined, value: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { if (types.isString(value)) { - return this.resolveStringPromise(folderUri, value, commandValueMapping, resolvedVariables); + return this.resolveStringPromise(folderUri, value, commandValueMapping, resolveContributed, resolvedVariables); } else if (types.isArray(value)) { - return Promise.all(value.map(s => this.recursiveResolvePromise(folderUri, s, commandValueMapping, resolvedVariables))); + return Promise.all(value.map(s => this.recursiveResolvePromise(folderUri, s, resolveContributed, commandValueMapping, resolvedVariables))); } else if (types.isObject(value)) { let result: IStringDictionary | string[]> = Object.create(null); const keys = Object.keys(value); for (let key of keys) { - const replaced = await this.resolveStringPromise(folderUri, key, commandValueMapping, resolvedVariables); - result[replaced] = await this.recursiveResolvePromise(folderUri, value[key], commandValueMapping, resolvedVariables); + const replaced = await this.resolveStringPromise(folderUri, key, commandValueMapping, resolveContributed, resolvedVariables); + result[replaced] = await this.recursiveResolvePromise(folderUri, value[key], resolveContributed, commandValueMapping, resolvedVariables); } return result; } @@ -150,17 +150,19 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return replaced; } - private async resolveStringPromise(folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary | undefined, resolvedVariables?: Map): Promise { + private async resolveStringPromise(folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary | undefined, resolveContributed: boolean, resolvedVariables?: Map): Promise { // loop through all variables occurrences in 'value' const matches = value.match(AbstractVariableResolverService.VARIABLE_REGEXP); const replaces: Map = new Map(); if (!matches) { return value; } - for (const match of matches) { - const evaluate = await this.evaluateSingleContributedVariable(match, match.match(AbstractVariableResolverService.VARIABLE_REGEXP_SINGLE)![1]); - if (evaluate !== match) { - replaces.set(match, evaluate); + if (resolveContributed) { + for (const match of matches) { + const evaluate = await this.evaluateSingleContributedVariable(match, match.match(AbstractVariableResolverService.VARIABLE_REGEXP_SINGLE)![1]); + if (evaluate !== match) { + replaces.set(match, evaluate); + } } } From 89dd1725e3c70afbe9a18436994d15340333e8e2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 16:22:11 +0200 Subject: [PATCH 103/435] fixes #81727 --- src/vs/base/browser/ui/tree/abstractTree.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index fd67ae50931..68754b3e448 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -855,7 +855,13 @@ class TypeFilterController implements IDisposable { } dispose() { - this.disable(); + if (this._enabled) { + this.domNode.remove(); + this.enabledDisposables = dispose(this.enabledDisposables); + this._enabled = false; + this.triggered = false; + } + this._onDidChangePattern.dispose(); this.disposables = dispose(this.disposables); } From 085e845f224d549ceab9c980effb1de8802d6fd2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 16:24:06 +0200 Subject: [PATCH 104/435] limit panelview animations to expansion fixes #81723 fixes #81722 --- src/vs/base/browser/ui/splitview/panelview.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 7c337dc62da..875537e8817 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { $, append, addClass, removeClass, toggleClass, trackFocus, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; +import { $, append, addClass, removeClass, toggleClass, trackFocus } from 'vs/base/browser/dom'; import { firstIndex } from 'vs/base/common/arrays'; import { Color, RGBA } from 'vs/base/common/color'; import { SplitView, IView } from './splitview'; @@ -58,6 +58,9 @@ export abstract class Panel extends Disposable implements IView { private readonly _onDidChange = this._register(new Emitter()); readonly onDidChange: Event = this._onDidChange.event; + private readonly _onDidChangeExpansionState = this._register(new Emitter()); + readonly onDidChangeExpansionState: Event = this._onDidChangeExpansionState.event; + get draggableElement(): HTMLElement { return this.header; } @@ -144,6 +147,7 @@ export abstract class Panel extends Disposable implements IView { }, 200); } + this._onDidChangeExpansionState.fire(expanded); this._onDidChange.fire(expanded ? this.expandedSize : undefined); return true; } @@ -391,13 +395,7 @@ export class PanelView extends Disposable { addPanel(panel: Panel, size: number, index = this.splitview.length): void { const disposables = new DisposableStore(); - - // https://github.com/Microsoft/vscode/issues/59950 - let shouldAnimate = false; - disposables.add(scheduleAtNextAnimationFrame(() => shouldAnimate = true)); - - disposables.add(Event.filter(panel.onDidChange, () => shouldAnimate) - (this.setupAnimation, this)); + panel.onDidChangeExpansionState(this.setupAnimation, this, disposables); const panelItem = { panel, disposable: disposables }; this.panelItems.splice(index, 0, panelItem); From 2943151b3aecaef0bb5ebec2c7188495df0cbfaf Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Oct 2019 16:37:22 +0200 Subject: [PATCH 105/435] fixes #81567 --- src/vs/workbench/contrib/debug/common/debugUtils.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/debug/common/debugUtils.ts b/src/vs/workbench/contrib/debug/common/debugUtils.ts index 8dbe2680204..3af63c8db6e 100644 --- a/src/vs/workbench/contrib/debug/common/debugUtils.ts +++ b/src/vs/workbench/contrib/debug/common/debugUtils.ts @@ -196,6 +196,9 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA: case 'setBreakpoints': fixSourcePath(true, (request.arguments).source); break; + case 'breakpointLocations': + fixSourcePath(true, (request.arguments).source); + break; case 'source': fixSourcePath(true, (request.arguments).source); break; From 0f4875f5e749e84b794dd46519e5fe45113e540d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 2 Oct 2019 16:54:30 +0200 Subject: [PATCH 106/435] fixes #81846 --- .../contrib/scm/browser/repositoryPanel.ts | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index db634534373..55c19287d50 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -50,6 +50,7 @@ import { localize } from 'vs/nls'; import { flatten } from 'vs/base/common/arrays'; import { memoize } from 'vs/base/common/decorators'; import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; type TreeElement = ISCMResourceGroup | IBranchNode | ISCMResource; @@ -389,8 +390,8 @@ function asTreeElement(node: INode, incompressi } const enum ViewModelMode { - List, - Tree + List = 'list', + Tree = 'tree' } class ViewModel { @@ -547,7 +548,8 @@ export class RepositoryPanel extends ViewletPanel { @IInstantiationService protected instantiationService: IInstantiationService, @IConfigurationService protected configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService, - @IMenuService protected menuService: IMenuService + @IMenuService protected menuService: IMenuService, + @IStorageService private storageService: IStorageService ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService); @@ -694,23 +696,27 @@ export class RepositoryPanel extends ViewletPanel { this._register(this.tree.onContextMenu(this.onListContextMenu, this)); this._register(this.tree); - const mode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; + let mode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; + + const rootUri = this.repository.provider.rootUri; + + if (typeof rootUri !== 'undefined') { + const storageMode = this.storageService.get(`scm.repository.viewMode:${rootUri.toString()}`, StorageScope.WORKSPACE) as ViewModelMode; + + if (typeof storageMode === 'string') { + mode = storageMode; + } + } + this.viewModel = new ViewModel(this.repository.provider.groups, this.tree, mode); this._register(this.viewModel); addClass(this.listContainer, 'file-icon-themable-tree'); addClass(this.listContainer, 'show-file-icons'); - const updateIndentStyles = (theme: IFileIconTheme) => { - toggleClass(this.listContainer, 'list-view-mode', this.viewModel.mode === ViewModelMode.List); - toggleClass(this.listContainer, 'tree-view-mode', this.viewModel.mode === ViewModelMode.Tree); - toggleClass(this.listContainer, 'align-icons-and-twisties', this.viewModel.mode === ViewModelMode.Tree && theme.hasFileIcons && !theme.hasFolderIcons); - toggleClass(this.listContainer, 'hide-arrows', this.viewModel.mode === ViewModelMode.Tree && theme.hidesExplorerArrows === true); - }; - - updateIndentStyles(this.themeService.getFileIconTheme()); - this._register(this.themeService.onDidFileIconThemeChange(updateIndentStyles)); - this._register(this.viewModel.onDidChangeMode(() => updateIndentStyles(this.themeService.getFileIconTheme()))); + this.updateIndentStyles(this.themeService.getFileIconTheme()); + this._register(this.themeService.onDidFileIconThemeChange(this.updateIndentStyles, this)); + this._register(this.viewModel.onDidChangeMode(this.onDidChangeMode, this)); this.toggleViewModelModeAction = new ToggleViewModeAction(this.viewModel); this._register(this.toggleViewModelModeAction); @@ -720,6 +726,25 @@ export class RepositoryPanel extends ViewletPanel { this.updateActions(); } + private updateIndentStyles(theme: IFileIconTheme): void { + toggleClass(this.listContainer, 'list-view-mode', this.viewModel.mode === ViewModelMode.List); + toggleClass(this.listContainer, 'tree-view-mode', this.viewModel.mode === ViewModelMode.Tree); + toggleClass(this.listContainer, 'align-icons-and-twisties', this.viewModel.mode === ViewModelMode.Tree && theme.hasFileIcons && !theme.hasFolderIcons); + toggleClass(this.listContainer, 'hide-arrows', this.viewModel.mode === ViewModelMode.Tree && theme.hidesExplorerArrows === true); + } + + private onDidChangeMode(): void { + this.updateIndentStyles(this.themeService.getFileIconTheme()); + + const rootUri = this.repository.provider.rootUri; + + if (typeof rootUri === 'undefined') { + return; + } + + this.storageService.store(`scm.repository.viewMode:${rootUri.toString()}`, this.viewModel.mode, StorageScope.WORKSPACE); + } + layoutBody(height: number | undefined = this.cachedHeight, width: number | undefined = this.cachedWidth): void { if (height === undefined) { return; From ab529dcd833858c063af7ed6bc7510b42e917326 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 2 Oct 2019 17:44:41 +0200 Subject: [PATCH 107/435] fixes #81852 --- .../workbench/contrib/files/common/editors/fileEditorInput.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts index 0072552bf87..662bcc8347a 100644 --- a/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts @@ -82,6 +82,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { private onModelOrphanedChanged(e: TextFileModelChangeEvent): void { if (e.resource.toString() === this.resource.toString()) { + FileEditorInput.MEMOIZER.clear(); this._onDidChangeLabel.fire(); } } @@ -209,6 +210,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { private decorateLabel(label: string): string { const model = this.textFileService.models.get(this.resource); + if (model && model.hasState(ModelState.ORPHAN)) { return localize('orphanedFile', "{0} (deleted)", label); } From e5557b7e6e869598465663f1e99fc5f05e4d0f5a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 1 Oct 2019 22:08:31 -0700 Subject: [PATCH 108/435] Reapply c057a4b9c73ce820e0c1a02797bf9f06bd638e86 Fixes integration tests --- .../contrib/customEditor/browser/customEditors.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 20930bf6242..347a5eb3164 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -174,11 +174,20 @@ export class CustomEditorService implements ICustomEditorService { if (group) { const existingEditors = group.editors.filter(editor => editor.getResource() && isEqual(editor.getResource()!, resource)); if (existingEditors.length) { + const existing = existingEditors[0]; + if (existing.matches(input)) { + return; + } + await this.editorService.replaceEditors([{ - editor: existingEditors[0], + editor: existing, replacement: input, options: options ? EditorOptions.create(options) : undefined, }], group); + + if (existing instanceof CustomFileEditorInput) { + existing.dispose(); + } } } return this.editorService.openEditor(input, options, group); From b7cc9ca8223080799c8654fa77e0200898ffb183 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 10:39:26 -0700 Subject: [PATCH 109/435] Update md grammar --- .../syntaxes/markdown.tmLanguage.json | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index 61b975b7015..269140f643b 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.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/vscode-markdown-tm-grammar/commit/00b05ebe6850083664d92d0eba6e5ee8f153baa6", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/46724e2885f9557400ed91727d75c3574ceded3a", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -1682,6 +1682,39 @@ } ] }, + "fenced_code_block_log": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(log)(\\s+[^`~]*)?$)", + "name": "markup.fenced_code.block.markdown", + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "4": { + "name": "fenced_code.block.language.markdown" + }, + "5": { + "name": "fenced_code.block.language.attributes.markdown" + } + }, + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", + "contentName": "meta.embedded.block.log", + "patterns": [ + { + "include": "text.log" + } + ] + } + ] + }, "fenced_code_block": { "patterns": [ { @@ -1831,6 +1864,9 @@ { "include": "#fenced_code_block_markdown" }, + { + "include": "#fenced_code_block_log" + }, { "include": "#fenced_code_block_unknown" } From b058a2831a30cf71e8f0d216cf841071eb3db957 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 10:44:00 -0700 Subject: [PATCH 110/435] Correctly style image loading indicator for various themes Wrong class name was being used --- extensions/image-preview/media/main.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/image-preview/media/main.css b/extensions/image-preview/media/main.css index 57dface9cad..913d2b46726 100644 --- a/extensions/image-preview/media/main.css +++ b/extensions/image-preview/media/main.css @@ -106,10 +106,10 @@ body img { margin: 1em; } -.vscode-dark .loading { +.vscode-dark .loading-indicator { background-image: url('./loading-dark.svg'); } -.vscode-high-contrast .loading { +.vscode-high-contrast .loading-indicator { background-image: url('./loading-hc.svg'); } From e2f1ee3573513e3f8f849b8995efd68bf9e7640e Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 2 Oct 2019 10:58:01 -0700 Subject: [PATCH 111/435] fixes #81838 --- src/vs/workbench/browser/parts/titlebar/titlebarPart.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index d064cc008d6..c690b885a6c 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -338,6 +338,11 @@ export class TitlebarPart extends Part implements ITitleService { } private installMenubar(): void { + // If the menubar is already installed, skip + if (this.menubar) { + return; + } + this.customMenubar = this._register(this.instantiationService.createInstance(CustomMenubarControl)); this.menubar = this.element.insertBefore($('div.menubar'), this.title); From a1b7714d2614b391c252ed04dff5738e380e7b49 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Wed, 2 Oct 2019 21:11:42 +0200 Subject: [PATCH 112/435] Schema for attached container configurations (fixes microsoft/vscode-remote-release#1577) --- extensions/configuration-editing/package.json | 4 +++ .../schemas/attachContainer.schema.json | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 extensions/configuration-editing/schemas/attachContainer.schema.json diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index e6658a6d425..601bc9c8a78 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -105,6 +105,10 @@ { "fileMatch": "/.devcontainer.json", "url": "./schemas/devContainer.schema.json" + }, + { + "fileMatch": "%APP_SETTINGS_HOME%/globalStorage/ms-vscode-remote.remote-containers/imageConfigs/*.json", + "url": "./schemas/attachContainer.schema.json" } ] }, diff --git a/extensions/configuration-editing/schemas/attachContainer.schema.json b/extensions/configuration-editing/schemas/attachContainer.schema.json new file mode 100644 index 00000000000..5f3d28abb89 --- /dev/null +++ b/extensions/configuration-editing/schemas/attachContainer.schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/schema#", + "description": "Configures an attached to container", + "allowComments": true, + "type": "object", + "definitions": { + "attachContainer": { + "type": "object", + "properties": { + "workspaceFolder": { + "type": "string", + "description": "The path of the workspace folder inside the container." + }, + "forwardPorts": { + "type": "array", + "description": "Ports that are forwarded from the container to the local machine.", + "items": { + "type": "integer" + } + }, + "extensions": { + "type": "array", + "description": "An array of extensions that should be installed into the container.", + "items": { + "type": "string" + } + } + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/attachContainer" + } + ] +} From f7efcef2be8ab8853c12ee280ecafac052eb4880 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Wed, 2 Oct 2019 13:16:46 -0700 Subject: [PATCH 113/435] Fix #81845 --- extensions/css-language-features/package.json | 24 +++++++++++++++++++ .../css-language-features/package.nls.json | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 734deb0f2e3..6837c63d401 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -308,6 +308,18 @@ "order": 24, "title": "%scss.title%", "properties": { + "scss.completion.triggerPropertyValueCompletion": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%scss.completion.triggerPropertyValueCompletion.desc%" + }, + "scss.completion.completePropertyWithSemicolon": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%scss.completion.completePropertyWithSemicolon.desc%" + }, "scss.validate": { "type": "boolean", "scope": "resource", @@ -530,6 +542,18 @@ "type": "object", "title": "%less.title%", "properties": { + "less.completion.triggerPropertyValueCompletion": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%less.completion.triggerPropertyValueCompletion.desc%" + }, + "less.completion.completePropertyWithSemicolon": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%less.completion.completePropertyWithSemicolon.desc%" + }, "less.validate": { "type": "boolean", "scope": "resource", diff --git a/extensions/css-language-features/package.nls.json b/extensions/css-language-features/package.nls.json index 9126d9adf5e..30220ccf940 100644 --- a/extensions/css-language-features/package.nls.json +++ b/extensions/css-language-features/package.nls.json @@ -29,6 +29,8 @@ "css.validate.title": "Controls CSS validation and problem severities.", "css.validate.desc": "Enables or disables all validations.", "less.title": "LESS", + "less.completion.triggerPropertyValueCompletion.desc": "By default, VS Code triggers property value completion after selecting a CSS property. Use this setting to disable this behavior.", + "less.completion.completePropertyWithSemicolon.desc": "Insert semicolon at end of line when completing CSS properties", "less.lint.argumentsInColorFunction.desc": "Invalid number of parameters.", "less.lint.boxModel.desc": "Do not use `width` or `height` when using `padding` or `border`.", "less.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties.", @@ -51,6 +53,8 @@ "less.validate.title": "Controls LESS validation and problem severities.", "less.validate.desc": "Enables or disables all validations.", "scss.title": "SCSS (Sass)", + "scss.completion.triggerPropertyValueCompletion.desc": "By default, VS Code triggers property value completion after selecting a CSS property. Use this setting to disable this behavior.", + "scss.completion.completePropertyWithSemicolon.desc": "Insert semicolon at end of line when completing CSS properties", "scss.lint.argumentsInColorFunction.desc": "Invalid number of parameters.", "scss.lint.boxModel.desc": "Do not use `width` or `height` when using `padding` or `border`.", "scss.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties.", From 790c574ce46419992896c797a7b83ca2b625062c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 2 Oct 2019 13:34:52 -0700 Subject: [PATCH 114/435] Fix microsoft/vscode-remote-release#1573 --- src/vs/workbench/contrib/remote/browser/remote.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index ed0a250c322..14a04519113 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -433,8 +433,10 @@ export class RemoteViewlet extends ViewContainerViewlet implements IViewModel { } const descriptorAuthority = descriptor.viewDescriptor.remoteAuthority; - if (typeof descriptorAuthority === 'undefined' || descriptor.viewDescriptor.id === HelpPanel.ID) { + if (typeof descriptorAuthority === 'undefined') { panel.setExpanded(true); + } else if (descriptor.viewDescriptor.id === HelpPanel.ID) { + // Do nothing, keep the default behavior for Help } else { const descriptorAuthorityArr = Array.isArray(descriptorAuthority) ? descriptorAuthority : [descriptorAuthority]; if (descriptorAuthorityArr.indexOf(actualRemoteAuthority) >= 0) { From 8f83fbaa2dcb8ef17733fbab8f3af4ddedccca30 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 13:42:41 -0700 Subject: [PATCH 115/435] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c215d982d8b..c7d711adb1d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "dc014344371646422438f73f01ea6709c5ad19e7", + "distro": "e8ae0d57bfb843f8df1eb8d78aa894bd2b72e7f9", "author": { "name": "Microsoft Corporation" }, From e568cf539c0084047bda7e5afe9e410ebefc9664 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 14:03:36 -0700 Subject: [PATCH 116/435] Fix search smoke tests --- test/automation/src/search.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/automation/src/search.ts b/test/automation/src/search.ts index 2b8076cc27e..8f7767802f5 100644 --- a/test/automation/src/search.ts +++ b/test/automation/src/search.ts @@ -84,11 +84,11 @@ export class Search extends Viewlet { } async expandReplace(): Promise { - await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.collapse`); + await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.codicon-chevron-right`); } async collapseReplace(): Promise { - await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.expand`); + await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.codicon-chevron-down`); } async setReplaceText(text: string): Promise { @@ -100,12 +100,12 @@ export class Search extends Viewlet { await retry( () => this.code.waitAndClick(fileMatch), - () => this.code.waitForElement(`${fileMatch} .action-label.codicon.action-replace-all`, el => !!el && el.top > 0 && el.left > 0, 10) + () => this.code.waitForElement(`${fileMatch} .action-label.codicon.codicon-replace-all`, el => !!el && el.top > 0 && el.left > 0, 10) ); // ¯\_(ツ)_/¯ await new Promise(c => setTimeout(c, 500)); - await this.code.waitAndClick(`${fileMatch} .action-label.codicon.action-replace-all`); + await this.code.waitAndClick(`${fileMatch} .action-label.codicon.codicon-replace-all`); } async waitForResultText(text: string): Promise { From e28affc16b0d6cb30d8baa8ae352c390d5034452 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 14:07:08 -0700 Subject: [PATCH 117/435] Fix preferences smoke tests --- test/automation/src/keybindings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/automation/src/keybindings.ts b/test/automation/src/keybindings.ts index 70be12b2378..0e8739dd04c 100644 --- a/test/automation/src/keybindings.ts +++ b/test/automation/src/keybindings.ts @@ -24,7 +24,7 @@ export class KeybindingsEditor { await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item'); await this.code.waitForElement('.keybindings-list-container .monaco-list-row.keybinding-item.focused.selected'); - await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .codicon.add'); + await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .codicon.codicon-add'); await this.code.waitForActiveElement('.defineKeybindingWidget .monaco-inputbox input'); await this.code.dispatchKeybinding(keybinding); From 2235ebf5db5ca8e018541e5134a376e4a907299e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 14:09:29 -0700 Subject: [PATCH 118/435] Handle new vscode-resource format for md linkes Fixes #81849 This is a safer scoped fix, not the best one. Will look into removing most of this uri munging for october --- extensions/markdown-language-features/media/index.js | 8 ++++++-- .../markdown-language-features/preview-src/index.ts | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/extensions/markdown-language-features/media/index.js b/extensions/markdown-language-features/media/index.js index d46e19c8c97..2111928ba3a 100644 --- a/extensions/markdown-language-features/media/index.js +++ b/extensions/markdown-language-features/media/index.js @@ -752,7 +752,11 @@ document.addEventListener('click', event => { break; } if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { - const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)).split('#'); + const [path, fragment] = node.href + .replace(/^file:\/\//i, '') + .replace(/^vscode-resource:\/\/[^\/]+\//i, '') + .replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)) + .split('#'); messaging.postMessage('clickLink', { path, fragment }); event.preventDefault(); event.stopPropagation(); @@ -1005,4 +1009,4 @@ exports.getSettings = getSettings; /***/ }) /******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsTUFBTTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUI7QUFDcEU7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdIQUF3SCwyQ0FBMkM7QUFDbkssb0RBQW9ELGlCQUFpQjtBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQsT0FBTztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDOzs7Ozs7Ozs7Ozs7O0FDckpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixrQ0FBa0M7QUFDM0Q7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHlCQUF5QjtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLGlCQUFpQjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxpQkFBaUI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOzs7Ozs7Ozs7Ozs7O0FDdklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsSUFBSTtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbiBcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG4gXHRcdFx0XHRnZXQ6IGdldHRlclxuIFx0XHRcdH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSBmdW5jdGlvbihleHBvcnRzKSB7XG4gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gXCIuL3ByZXZpZXctc3JjL2luZGV4LnRzXCIpO1xuIiwiLyoqXG4gKiBsb2Rhc2ggKEN1c3RvbSBCdWlsZCkgPGh0dHBzOi8vbG9kYXNoLmNvbS8+XG4gKiBCdWlsZDogYGxvZGFzaCBtb2R1bGFyaXplIGV4cG9ydHM9XCJucG1cIiAtbyAuL2BcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzIDxodHRwczovL2pxdWVyeS5vcmcvPlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICogQmFzZWQgb24gVW5kZXJzY29yZS5qcyAxLjguMyA8aHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvTElDRU5TRT5cbiAqIENvcHlyaWdodCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICovXG5cbi8qKiBVc2VkIGFzIHRoZSBgVHlwZUVycm9yYCBtZXNzYWdlIGZvciBcIkZ1bmN0aW9uc1wiIG1ldGhvZHMuICovXG52YXIgRlVOQ19FUlJPUl9URVhUID0gJ0V4cGVjdGVkIGEgZnVuY3Rpb24nO1xuXG4vKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB2YXJpb3VzIGBOdW1iZXJgIGNvbnN0YW50cy4gKi9cbnZhciBOQU4gPSAwIC8gMDtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nO1xuXG4vKiogVXNlZCB0byBtYXRjaCBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlLiAqL1xudmFyIHJlVHJpbSA9IC9eXFxzK3xcXHMrJC9nO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmFkIHNpZ25lZCBoZXhhZGVjaW1hbCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNCYWRIZXggPSAvXlstK10weFswLTlhLWZdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJpbmFyeSBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNCaW5hcnkgPSAvXjBiWzAxXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBvY3RhbCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNPY3RhbCA9IC9eMG9bMC03XSskL2k7XG5cbi8qKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB3aXRob3V0IGEgZGVwZW5kZW5jeSBvbiBgcm9vdGAuICovXG52YXIgZnJlZVBhcnNlSW50ID0gcGFyc2VJbnQ7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMuICovXG52YXIgZnJlZUdsb2JhbCA9IHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsICYmIGdsb2JhbC5PYmplY3QgPT09IE9iamVjdCAmJiBnbG9iYWw7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgc2VsZmAuICovXG52YXIgZnJlZVNlbGYgPSB0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmICYmIHNlbGYuT2JqZWN0ID09PSBPYmplY3QgJiYgc2VsZjtcblxuLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG52YXIgcm9vdCA9IGZyZWVHbG9iYWwgfHwgZnJlZVNlbGYgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gKiBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9iamVjdFRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heCxcbiAgICBuYXRpdmVNaW4gPSBNYXRoLm1pbjtcblxuLyoqXG4gKiBHZXRzIHRoZSB0aW1lc3RhbXAgb2YgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2VcbiAqIHRoZSBVbml4IGVwb2NoICgxIEphbnVhcnkgMTk3MCAwMDowMDowMCBVVEMpLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMi40LjBcbiAqIEBjYXRlZ29yeSBEYXRlXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lc3RhbXAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uZGVmZXIoZnVuY3Rpb24oc3RhbXApIHtcbiAqICAgY29uc29sZS5sb2coXy5ub3coKSAtIHN0YW1wKTtcbiAqIH0sIF8ubm93KCkpO1xuICogLy8gPT4gTG9ncyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBpdCB0b29rIGZvciB0aGUgZGVmZXJyZWQgaW52b2NhdGlvbi5cbiAqL1xudmFyIG5vdyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcm9vdC5EYXRlLm5vdygpO1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVib3VuY2VkIGZ1bmN0aW9uIHRoYXQgZGVsYXlzIGludm9raW5nIGBmdW5jYCB1bnRpbCBhZnRlciBgd2FpdGBcbiAqIG1pbGxpc2Vjb25kcyBoYXZlIGVsYXBzZWQgc2luY2UgdGhlIGxhc3QgdGltZSB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHdhc1xuICogaW52b2tlZC4gVGhlIGRlYm91bmNlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGAgbWV0aG9kIHRvIGNhbmNlbFxuICogZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG8gaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uXG4gKiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYCBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGVcbiAqIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YCB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWRcbiAqIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnRcbiAqIGNhbGxzIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgXG4gKiBpbnZvY2F0aW9uLlxuICpcbiAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uXG4gKiBpcyBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gKlxuICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gKiB1bnRpbCB0byB0aGUgbmV4dCB0aWNrLCBzaW1pbGFyIHRvIGBzZXRUaW1lb3V0YCB3aXRoIGEgdGltZW91dCBvZiBgMGAuXG4gKlxuICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLmRlYm91bmNlYCBhbmQgYF8udGhyb3R0bGVgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVib3VuY2UuXG4gKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkuXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz1mYWxzZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMubWF4V2FpdF1cbiAqICBUaGUgbWF4aW11bSB0aW1lIGBmdW5jYCBpcyBhbGxvd2VkIHRvIGJlIGRlbGF5ZWQgYmVmb3JlIGl0J3MgaW52b2tlZC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZGVib3VuY2VkIGZ1bmN0aW9uLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBBdm9pZCBjb3N0bHkgY2FsY3VsYXRpb25zIHdoaWxlIHRoZSB3aW5kb3cgc2l6ZSBpcyBpbiBmbHV4LlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3Jlc2l6ZScsIF8uZGVib3VuY2UoY2FsY3VsYXRlTGF5b3V0LCAxNTApKTtcbiAqXG4gKiAvLyBJbnZva2UgYHNlbmRNYWlsYCB3aGVuIGNsaWNrZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxscy5cbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmRlYm91bmNlKHNlbmRNYWlsLCAzMDAsIHtcbiAqICAgJ2xlYWRpbmcnOiB0cnVlLFxuICogICAndHJhaWxpbmcnOiBmYWxzZVxuICogfSkpO1xuICpcbiAqIC8vIEVuc3VyZSBgYmF0Y2hMb2dgIGlzIGludm9rZWQgb25jZSBhZnRlciAxIHNlY29uZCBvZiBkZWJvdW5jZWQgY2FsbHMuXG4gKiB2YXIgZGVib3VuY2VkID0gXy5kZWJvdW5jZShiYXRjaExvZywgMjUwLCB7ICdtYXhXYWl0JzogMTAwMCB9KTtcbiAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAqIGpRdWVyeShzb3VyY2UpLm9uKCdtZXNzYWdlJywgZGVib3VuY2VkKTtcbiAqXG4gKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIGRlYm91bmNlZCBpbnZvY2F0aW9uLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgZGVib3VuY2VkLmNhbmNlbCk7XG4gKi9cbmZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgdmFyIGxhc3RBcmdzLFxuICAgICAgbGFzdFRoaXMsXG4gICAgICBtYXhXYWl0LFxuICAgICAgcmVzdWx0LFxuICAgICAgdGltZXJJZCxcbiAgICAgIGxhc3RDYWxsVGltZSxcbiAgICAgIGxhc3RJbnZva2VUaW1lID0gMCxcbiAgICAgIGxlYWRpbmcgPSBmYWxzZSxcbiAgICAgIG1heGluZyA9IGZhbHNlLFxuICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICB9XG4gIHdhaXQgPSB0b051bWJlcih3YWl0KSB8fCAwO1xuICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICBsZWFkaW5nID0gISFvcHRpb25zLmxlYWRpbmc7XG4gICAgbWF4aW5nID0gJ21heFdhaXQnIGluIG9wdGlvbnM7XG4gICAgbWF4V2FpdCA9IG1heGluZyA/IG5hdGl2ZU1heCh0b051bWJlcihvcHRpb25zLm1heFdhaXQpIHx8IDAsIHdhaXQpIDogbWF4V2FpdDtcbiAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICB9XG5cbiAgZnVuY3Rpb24gaW52b2tlRnVuYyh0aW1lKSB7XG4gICAgdmFyIGFyZ3MgPSBsYXN0QXJncyxcbiAgICAgICAgdGhpc0FyZyA9IGxhc3RUaGlzO1xuXG4gICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gbGVhZGluZ0VkZ2UodGltZSkge1xuICAgIC8vIFJlc2V0IGFueSBgbWF4V2FpdGAgdGltZXIuXG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIC8vIFN0YXJ0IHRoZSB0aW1lciBmb3IgdGhlIHRyYWlsaW5nIGVkZ2UuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAvLyBJbnZva2UgdGhlIGxlYWRpbmcgZWRnZS5cbiAgICByZXR1cm4gbGVhZGluZyA/IGludm9rZUZ1bmModGltZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiByZW1haW5pbmdXYWl0KHRpbWUpIHtcbiAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lLFxuICAgICAgICByZXN1bHQgPSB3YWl0IC0gdGltZVNpbmNlTGFzdENhbGw7XG5cbiAgICByZXR1cm4gbWF4aW5nID8gbmF0aXZlTWluKHJlc3VsdCwgbWF4V2FpdCAtIHRpbWVTaW5jZUxhc3RJbnZva2UpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gc2hvdWxkSW52b2tlKHRpbWUpIHtcbiAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lO1xuXG4gICAgLy8gRWl0aGVyIHRoaXMgaXMgdGhlIGZpcnN0IGNhbGwsIGFjdGl2aXR5IGhhcyBzdG9wcGVkIGFuZCB3ZSdyZSBhdCB0aGVcbiAgICAvLyB0cmFpbGluZyBlZGdlLCB0aGUgc3lzdGVtIHRpbWUgaGFzIGdvbmUgYmFja3dhcmRzIGFuZCB3ZSdyZSB0cmVhdGluZ1xuICAgIC8vIGl0IGFzIHRoZSB0cmFpbGluZyBlZGdlLCBvciB3ZSd2ZSBoaXQgdGhlIGBtYXhXYWl0YCBsaW1pdC5cbiAgICByZXR1cm4gKGxhc3RDYWxsVGltZSA9PT0gdW5kZWZpbmVkIHx8ICh0aW1lU2luY2VMYXN0Q2FsbCA+PSB3YWl0KSB8fFxuICAgICAgKHRpbWVTaW5jZUxhc3RDYWxsIDwgMCkgfHwgKG1heGluZyAmJiB0aW1lU2luY2VMYXN0SW52b2tlID49IG1heFdhaXQpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRpbWVyRXhwaXJlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpO1xuICAgIGlmIChzaG91bGRJbnZva2UodGltZSkpIHtcbiAgICAgIHJldHVybiB0cmFpbGluZ0VkZ2UodGltZSk7XG4gICAgfVxuICAgIC8vIFJlc3RhcnQgdGhlIHRpbWVyLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgcmVtYWluaW5nV2FpdCh0aW1lKSk7XG4gIH1cblxuICBmdW5jdGlvbiB0cmFpbGluZ0VkZ2UodGltZSkge1xuICAgIHRpbWVySWQgPSB1bmRlZmluZWQ7XG5cbiAgICAvLyBPbmx5IGludm9rZSBpZiB3ZSBoYXZlIGBsYXN0QXJnc2Agd2hpY2ggbWVhbnMgYGZ1bmNgIGhhcyBiZWVuXG4gICAgLy8gZGVib3VuY2VkIGF0IGxlYXN0IG9uY2UuXG4gICAgaWYgKHRyYWlsaW5nICYmIGxhc3RBcmdzKSB7XG4gICAgICByZXR1cm4gaW52b2tlRnVuYyh0aW1lKTtcbiAgICB9XG4gICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgIGlmICh0aW1lcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICB9XG4gICAgbGFzdEludm9rZVRpbWUgPSAwO1xuICAgIGxhc3RBcmdzID0gbGFzdENhbGxUaW1lID0gbGFzdFRoaXMgPSB0aW1lcklkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgcmV0dXJuIHRpbWVySWQgPT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IHRyYWlsaW5nRWRnZShub3coKSk7XG4gIH1cblxuICBmdW5jdGlvbiBkZWJvdW5jZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKSxcbiAgICAgICAgaXNJbnZva2luZyA9IHNob3VsZEludm9rZSh0aW1lKTtcblxuICAgIGxhc3RBcmdzID0gYXJndW1lbnRzO1xuICAgIGxhc3RUaGlzID0gdGhpcztcbiAgICBsYXN0Q2FsbFRpbWUgPSB0aW1lO1xuXG4gICAgaWYgKGlzSW52b2tpbmcpIHtcbiAgICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGxlYWRpbmdFZGdlKGxhc3RDYWxsVGltZSk7XG4gICAgICB9XG4gICAgICBpZiAobWF4aW5nKSB7XG4gICAgICAgIC8vIEhhbmRsZSBpbnZvY2F0aW9ucyBpbiBhIHRpZ2h0IGxvb3AuXG4gICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgICAgIHJldHVybiBpbnZva2VGdW5jKGxhc3RDYWxsVGltZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgZGVib3VuY2VkLmNhbmNlbCA9IGNhbmNlbDtcbiAgZGVib3VuY2VkLmZsdXNoID0gZmx1c2g7XG4gIHJldHVybiBkZWJvdW5jZWQ7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHRocm90dGxlZCBmdW5jdGlvbiB0aGF0IG9ubHkgaW52b2tlcyBgZnVuY2AgYXQgbW9zdCBvbmNlIHBlclxuICogZXZlcnkgYHdhaXRgIG1pbGxpc2Vjb25kcy4gVGhlIHRocm90dGxlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGBcbiAqIG1ldGhvZCB0byBjYW5jZWwgZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG9cbiAqIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYFxuICogc2hvdWxkIGJlIGludm9rZWQgb24gdGhlIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YFxuICogdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZVxuICogdGhyb3R0bGVkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50IGNhbGxzIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJuIHRoZVxuICogcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYCBpbnZvY2F0aW9uLlxuICpcbiAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uXG4gKiBpcyBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gKlxuICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gKiB1bnRpbCB0byB0aGUgbmV4dCB0aWNrLCBzaW1pbGFyIHRvIGBzZXRUaW1lb3V0YCB3aXRoIGEgdGltZW91dCBvZiBgMGAuXG4gKlxuICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLnRocm90dGxlYCBhbmQgYF8uZGVib3VuY2VgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gdGhyb3R0bGUuXG4gKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gdGhyb3R0bGUgaW52b2NhdGlvbnMgdG8uXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBBdm9pZCBleGNlc3NpdmVseSB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgc2Nyb2xsaW5nLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCkpO1xuICpcbiAqIC8vIEludm9rZSBgcmVuZXdUb2tlbmAgd2hlbiB0aGUgY2xpY2sgZXZlbnQgaXMgZmlyZWQsIGJ1dCBub3QgbW9yZSB0aGFuIG9uY2UgZXZlcnkgNSBtaW51dGVzLlxuICogdmFyIHRocm90dGxlZCA9IF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7ICd0cmFpbGluZyc6IGZhbHNlIH0pO1xuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIHRocm90dGxlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyB0aHJvdHRsZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIHRocm90dGxlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiB0aHJvdHRsZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsZWFkaW5nID0gdHJ1ZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICBsZWFkaW5nID0gJ2xlYWRpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMubGVhZGluZyA6IGxlYWRpbmc7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuICByZXR1cm4gZGVib3VuY2UoZnVuYywgd2FpdCwge1xuICAgICdsZWFkaW5nJzogbGVhZGluZyxcbiAgICAnbWF4V2FpdCc6IHdhaXQsXG4gICAgJ3RyYWlsaW5nJzogdHJhaWxpbmdcbiAgfSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgdGhlXG4gKiBbbGFuZ3VhZ2UgdHlwZV0oaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWVjbWFzY3JpcHQtbGFuZ3VhZ2UtdHlwZXMpXG4gKiBvZiBgT2JqZWN0YC4gKGUuZy4gYXJyYXlzLCBmdW5jdGlvbnMsIG9iamVjdHMsIHJlZ2V4ZXMsIGBuZXcgTnVtYmVyKDApYCwgYW5kIGBuZXcgU3RyaW5nKCcnKWApXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNPYmplY3Qoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KF8ubm9vcCk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICByZXR1cm4gISF2YWx1ZSAmJiAodHlwZSA9PSAnb2JqZWN0JyB8fCB0eXBlID09ICdmdW5jdGlvbicpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLiBBIHZhbHVlIGlzIG9iamVjdC1saWtlIGlmIGl0J3Mgbm90IGBudWxsYFxuICogYW5kIGhhcyBhIGB0eXBlb2ZgIHJlc3VsdCBvZiBcIm9iamVjdFwiLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKF8ubm9vcCk7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3RMaWtlKHZhbHVlKSB7XG4gIHJldHVybiAhIXZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0Jztcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN5bWJvbGAgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHN5bWJvbCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzU3ltYm9sKFN5bWJvbC5pdGVyYXRvcik7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1N5bWJvbCgnYWJjJyk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc1N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdzeW1ib2wnIHx8XG4gICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gc3ltYm9sVGFnKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgbnVtYmVyLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgbnVtYmVyLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLnRvTnVtYmVyKDMuMik7XG4gKiAvLyA9PiAzLjJcbiAqXG4gKiBfLnRvTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICogLy8gPT4gNWUtMzI0XG4gKlxuICogXy50b051bWJlcihJbmZpbml0eSk7XG4gKiAvLyA9PiBJbmZpbml0eVxuICpcbiAqIF8udG9OdW1iZXIoJzMuMicpO1xuICogLy8gPT4gMy4yXG4gKi9cbmZ1bmN0aW9uIHRvTnVtYmVyKHZhbHVlKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgIHJldHVybiBOQU47XG4gIH1cbiAgaWYgKGlzT2JqZWN0KHZhbHVlKSkge1xuICAgIHZhciBvdGhlciA9IHR5cGVvZiB2YWx1ZS52YWx1ZU9mID09ICdmdW5jdGlvbicgPyB2YWx1ZS52YWx1ZU9mKCkgOiB2YWx1ZTtcbiAgICB2YWx1ZSA9IGlzT2JqZWN0KG90aGVyKSA/IChvdGhlciArICcnKSA6IG90aGVyO1xuICB9XG4gIGlmICh0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6ICt2YWx1ZTtcbiAgfVxuICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UocmVUcmltLCAnJyk7XG4gIHZhciBpc0JpbmFyeSA9IHJlSXNCaW5hcnkudGVzdCh2YWx1ZSk7XG4gIHJldHVybiAoaXNCaW5hcnkgfHwgcmVJc09jdGFsLnRlc3QodmFsdWUpKVxuICAgID8gZnJlZVBhcnNlSW50KHZhbHVlLnNsaWNlKDIpLCBpc0JpbmFyeSA/IDIgOiA4KVxuICAgIDogKHJlSXNCYWRIZXgudGVzdCh2YWx1ZSkgPyBOQU4gOiArdmFsdWUpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRocm90dGxlO1xuIiwidmFyIGc7XHJcblxyXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxyXG5nID0gKGZ1bmN0aW9uKCkge1xyXG5cdHJldHVybiB0aGlzO1xyXG59KSgpO1xyXG5cclxudHJ5IHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcclxuXHRnID0gZyB8fCBGdW5jdGlvbihcInJldHVybiB0aGlzXCIpKCkgfHwgKDEsIGV2YWwpKFwidGhpc1wiKTtcclxufSBjYXRjaCAoZSkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgdGhlIHdpbmRvdyByZWZlcmVuY2UgaXMgYXZhaWxhYmxlXHJcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XHJcbn1cclxuXHJcbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cclxuLy8gV2UgcmV0dXJuIHVuZGVmaW5lZCwgaW5zdGVhZCBvZiBub3RoaW5nIGhlcmUsIHNvIGl0J3NcclxuLy8gZWFzaWVyIHRvIGhhbmRsZSB0aGlzIGNhc2UuIGlmKCFnbG9iYWwpIHsgLi4ufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBnO1xyXG4iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuY29uc3Qgc2Nyb2xsX3N5bmNfMSA9IHJlcXVpcmUoXCIuL3Njcm9sbC1zeW5jXCIpO1xuY2xhc3MgQWN0aXZlTGluZU1hcmtlciB7XG4gICAgb25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uKGxpbmUpIHtcbiAgICAgICAgY29uc3QgeyBwcmV2aW91cyB9ID0gc2Nyb2xsX3N5bmNfMS5nZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZShwcmV2aW91cyAmJiBwcmV2aW91cy5lbGVtZW50KTtcbiAgICB9XG4gICAgX3VwZGF0ZShiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5fdW5tYXJrQWN0aXZlRWxlbWVudCh0aGlzLl9jdXJyZW50KTtcbiAgICAgICAgdGhpcy5fbWFya0FjdGl2ZUVsZW1lbnQoYmVmb3JlKTtcbiAgICAgICAgdGhpcy5fY3VycmVudCA9IGJlZm9yZTtcbiAgICB9XG4gICAgX3VubWFya0FjdGl2ZUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lLnJlcGxhY2UoL1xcYmNvZGUtYWN0aXZlLWxpbmVcXGIvZywgJycpO1xuICAgIH1cbiAgICBfbWFya0FjdGl2ZUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSArPSAnIGNvZGUtYWN0aXZlLWxpbmUnO1xuICAgIH1cbn1cbmV4cG9ydHMuQWN0aXZlTGluZU1hcmtlciA9IEFjdGl2ZUxpbmVNYXJrZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZnVuY3Rpb24gb25jZURvY3VtZW50TG9hZGVkKGYpIHtcbiAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnIHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICd1bmluaXRpYWxpemVkJykge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmKCk7XG4gICAgfVxufVxuZXhwb3J0cy5vbmNlRG9jdW1lbnRMb2FkZWQgPSBvbmNlRG9jdW1lbnRMb2FkZWQ7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgYWN0aXZlTGluZU1hcmtlcl8xID0gcmVxdWlyZShcIi4vYWN0aXZlTGluZU1hcmtlclwiKTtcbmNvbnN0IGV2ZW50c18xID0gcmVxdWlyZShcIi4vZXZlbnRzXCIpO1xuY29uc3QgbWVzc2FnaW5nXzEgPSByZXF1aXJlKFwiLi9tZXNzYWdpbmdcIik7XG5jb25zdCBzY3JvbGxfc3luY18xID0gcmVxdWlyZShcIi4vc2Nyb2xsLXN5bmNcIik7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5jb25zdCB0aHJvdHRsZSA9IHJlcXVpcmUoXCJsb2Rhc2gudGhyb3R0bGVcIik7XG5sZXQgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuY29uc3QgbWFya2VyID0gbmV3IGFjdGl2ZUxpbmVNYXJrZXJfMS5BY3RpdmVMaW5lTWFya2VyKCk7XG5jb25zdCBzZXR0aW5ncyA9IHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKTtcbmNvbnN0IHZzY29kZSA9IGFjcXVpcmVWc0NvZGVBcGkoKTtcbi8vIFNldCBWUyBDb2RlIHN0YXRlXG5sZXQgc3RhdGUgPSBzZXR0aW5nc18xLmdldERhdGEoJ2RhdGEtc3RhdGUnKTtcbnZzY29kZS5zZXRTdGF0ZShzdGF0ZSk7XG5jb25zdCBtZXNzYWdpbmcgPSBtZXNzYWdpbmdfMS5jcmVhdGVQb3N0ZXJGb3JWc0NvZGUodnNjb2RlKTtcbndpbmRvdy5jc3BBbGVydGVyLnNldFBvc3RlcihtZXNzYWdpbmcpO1xud2luZG93LnN0eWxlTG9hZGluZ01vbml0b3Iuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG53aW5kb3cub25sb2FkID0gKCkgPT4ge1xuICAgIHVwZGF0ZUltYWdlU2l6ZXMoKTtcbn07XG5ldmVudHNfMS5vbmNlRG9jdW1lbnRMb2FkZWQoKCkgPT4ge1xuICAgIGlmIChzZXR0aW5ncy5zY3JvbGxQcmV2aWV3V2l0aEVkaXRvcikge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBzY3JvbGwgdG8gZnJhZ21lbnQgaWYgYXZhaWxhYmxlXG4gICAgICAgICAgICBpZiAoc3RhdGUuZnJhZ21lbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gc2Nyb2xsX3N5bmNfMS5nZXRMaW5lRWxlbWVudEZvckZyYWdtZW50KHN0YXRlLmZyYWdtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGVsZW1lbnQubGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW5pdGlhbExpbmUgPSArc2V0dGluZ3MubGluZTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTmFOKGluaXRpYWxMaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGluaXRpYWxMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDApO1xuICAgIH1cbn0pO1xuY29uc3Qgb25VcGRhdGVWaWV3ID0gKCgpID0+IHtcbiAgICBjb25zdCBkb1Njcm9sbCA9IHRocm90dGxlKChsaW5lKSA9PiB7XG4gICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSk7XG4gICAgfSwgNTApO1xuICAgIHJldHVybiAobGluZSwgc2V0dGluZ3MpID0+IHtcbiAgICAgICAgaWYgKCFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgc2V0dGluZ3MubGluZSA9IGxpbmU7XG4gICAgICAgICAgICBkb1Njcm9sbChsaW5lKTtcbiAgICAgICAgfVxuICAgIH07XG59KSgpO1xubGV0IHVwZGF0ZUltYWdlU2l6ZXMgPSB0aHJvdHRsZSgoKSA9PiB7XG4gICAgY29uc3QgaW1hZ2VJbmZvID0gW107XG4gICAgbGV0IGltYWdlcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbWcnKTtcbiAgICBpZiAoaW1hZ2VzKSB7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpbWcgPSBpbWFnZXNbaV07XG4gICAgICAgICAgICBpZiAoaW1nLmNsYXNzTGlzdC5jb250YWlucygnbG9hZGluZycpKSB7XG4gICAgICAgICAgICAgICAgaW1nLmNsYXNzTGlzdC5yZW1vdmUoJ2xvYWRpbmcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGltYWdlSW5mby5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogaW1nLmlkLFxuICAgICAgICAgICAgICAgIGhlaWdodDogaW1nLmhlaWdodCxcbiAgICAgICAgICAgICAgICB3aWR0aDogaW1nLndpZHRoXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NhY2hlSW1hZ2VTaXplcycsIGltYWdlSW5mbyk7XG4gICAgfVxufSwgNTApO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHtcbiAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgdXBkYXRlSW1hZ2VTaXplcygpO1xufSwgdHJ1ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGV2ZW50ID0+IHtcbiAgICBpZiAoZXZlbnQuZGF0YS5zb3VyY2UgIT09IHNldHRpbmdzLnNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHN3aXRjaCAoZXZlbnQuZGF0YS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ29uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbic6XG4gICAgICAgICAgICBtYXJrZXIub25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uKGV2ZW50LmRhdGEubGluZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndXBkYXRlVmlldyc6XG4gICAgICAgICAgICBvblVwZGF0ZVZpZXcoZXZlbnQuZGF0YS5saW5lLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59LCBmYWxzZSk7XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGV2ZW50ID0+IHtcbiAgICBpZiAoIXNldHRpbmdzLmRvdWJsZUNsaWNrVG9Td2l0Y2hUb0VkaXRvcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIElnbm9yZSBjbGlja3Mgb24gbGlua3NcbiAgICBmb3IgKGxldCBub2RlID0gZXZlbnQudGFyZ2V0OyBub2RlOyBub2RlID0gbm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgIGlmIChub2RlLnRhZ05hbWUgPT09ICdBJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IG9mZnNldCA9IGV2ZW50LnBhZ2VZO1xuICAgIGNvbnN0IGxpbmUgPSBzY3JvbGxfc3luY18xLmdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCk7XG4gICAgaWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcbiAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdkaWRDbGljaycsIHsgbGluZTogTWF0aC5mbG9vcihsaW5lKSB9KTtcbiAgICB9XG59KTtcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZXZlbnQgPT4ge1xuICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgbm9kZSA9IGV2ZW50LnRhcmdldDtcbiAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICBpZiAobm9kZS50YWdOYW1lICYmIG5vZGUudGFnTmFtZSA9PT0gJ0EnICYmIG5vZGUuaHJlZikge1xuICAgICAgICAgICAgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJykuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobm9kZS5ocmVmLnN0YXJ0c1dpdGgoJ2ZpbGU6Ly8nKSB8fCBub2RlLmhyZWYuc3RhcnRzV2l0aCgndnNjb2RlLXJlc291cmNlOicpIHx8IG5vZGUuaHJlZi5zdGFydHNXaXRoKHNldHRpbmdzLndlYnZpZXdSZXNvdXJjZVJvb3QpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgW3BhdGgsIGZyYWdtZW50XSA9IG5vZGUuaHJlZi5yZXBsYWNlKC9eKGZpbGU6XFwvXFwvfHZzY29kZS1yZXNvdXJjZTopL2ksICcnKS5yZXBsYWNlKG5ldyBSZWdFeHAoYF4ke2VzY2FwZVJlZ0V4cChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KX1gKSkuc3BsaXQoJyMnKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NsaWNrTGluaycsIHsgcGF0aCwgZnJhZ21lbnQgfSk7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgfVxufSwgdHJ1ZSk7XG5pZiAoc2V0dGluZ3Muc2Nyb2xsRWRpdG9yV2l0aFByZXZpZXcpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhyb3R0bGUoKCkgPT4ge1xuICAgICAgICBpZiAoc2Nyb2xsRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHNjcm9sbERpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gc2Nyb2xsX3N5bmNfMS5nZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldCh3aW5kb3cuc2Nyb2xsWSk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgncmV2ZWFsTGluZScsIHsgbGluZSB9KTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5saW5lID0gbGluZTtcbiAgICAgICAgICAgICAgICB2c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgNTApKTtcbn1cbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKTtcbn1cbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5leHBvcnRzLmNyZWF0ZVBvc3RlckZvclZzQ29kZSA9ICh2c2NvZGUpID0+IHtcbiAgICByZXR1cm4gbmV3IGNsYXNzIHtcbiAgICAgICAgcG9zdE1lc3NhZ2UodHlwZSwgYm9keSkge1xuICAgICAgICAgICAgdnNjb2RlLnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgIHNvdXJjZTogc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNvdXJjZSxcbiAgICAgICAgICAgICAgICBib2R5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmZ1bmN0aW9uIGNsYW1wKG1pbiwgbWF4LCB2YWx1ZSkge1xuICAgIHJldHVybiBNYXRoLm1pbihtYXgsIE1hdGgubWF4KG1pbiwgdmFsdWUpKTtcbn1cbmZ1bmN0aW9uIGNsYW1wTGluZShsaW5lKSB7XG4gICAgcmV0dXJuIGNsYW1wKDAsIHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKS5saW5lQ291bnQgLSAxLCBsaW5lKTtcbn1cbmNvbnN0IGdldENvZGVMaW5lRWxlbWVudHMgPSAoKCkgPT4ge1xuICAgIGxldCBlbGVtZW50cztcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAoIWVsZW1lbnRzKSB7XG4gICAgICAgICAgICBlbGVtZW50cyA9IFt7IGVsZW1lbnQ6IGRvY3VtZW50LmJvZHksIGxpbmU6IDAgfV07XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS1saW5lJykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsaW5lID0gK2VsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWxpbmUnKTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzLnB1c2goeyBlbGVtZW50OiBlbGVtZW50LCBsaW5lIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgfTtcbn0pKCk7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBtYXAgdG8gYSBzcGVjaWZpYyB0YXJnZXQgbGluZSBpbiB0aGUgZWRpdG9yLlxuICpcbiAqIElmIGFuIGV4YWN0IG1hdGNoLCByZXR1cm5zIGEgc2luZ2xlIGVsZW1lbnQuIElmIHRoZSBsaW5lIGlzIGJldHdlZW4gZWxlbWVudHMsXG4gKiByZXR1cm5zIHRoZSBlbGVtZW50IHByaW9yIHRvIGFuZCB0aGUgZWxlbWVudCBhZnRlciB0aGUgZ2l2ZW4gbGluZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKHRhcmdldExpbmUpIHtcbiAgICBjb25zdCBsaW5lTnVtYmVyID0gTWF0aC5mbG9vcih0YXJnZXRMaW5lKTtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBsZXQgcHJldmlvdXMgPSBsaW5lc1swXSB8fCBudWxsO1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgbGluZXMpIHtcbiAgICAgICAgaWYgKGVudHJ5LmxpbmUgPT09IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzOiBlbnRyeSwgbmV4dDogdW5kZWZpbmVkIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZW50cnkubGluZSA+IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzLCBuZXh0OiBlbnRyeSB9O1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzID0gZW50cnk7XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzIH07XG59XG5leHBvcnRzLmdldEVsZW1lbnRzRm9yU291cmNlTGluZSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZTtcbi8qKlxuICogRmluZCB0aGUgaHRtbCBlbGVtZW50cyB0aGF0IGFyZSBhdCBhIHNwZWNpZmljIHBpeGVsIG9mZnNldCBvbiB0aGUgcGFnZS5cbiAqL1xuZnVuY3Rpb24gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IGxpbmVzID0gZ2V0Q29kZUxpbmVFbGVtZW50cygpO1xuICAgIGNvbnN0IHBvc2l0aW9uID0gb2Zmc2V0IC0gd2luZG93LnNjcm9sbFk7XG4gICAgbGV0IGxvID0gLTE7XG4gICAgbGV0IGhpID0gbGluZXMubGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAobG8gKyAxIDwgaGkpIHtcbiAgICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG8gKyBoaSkgLyAyKTtcbiAgICAgICAgY29uc3QgYm91bmRzID0gbGluZXNbbWlkXS5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBpZiAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgPj0gcG9zaXRpb24pIHtcbiAgICAgICAgICAgIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG8gPSBtaWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaGlFbGVtZW50ID0gbGluZXNbaGldO1xuICAgIGNvbnN0IGhpQm91bmRzID0gaGlFbGVtZW50LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgaWYgKGhpID49IDEgJiYgaGlCb3VuZHMudG9wID4gcG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgbG9FbGVtZW50ID0gbGluZXNbbG9dO1xuICAgICAgICByZXR1cm4geyBwcmV2aW91czogbG9FbGVtZW50LCBuZXh0OiBoaUVsZW1lbnQgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcHJldmlvdXM6IGhpRWxlbWVudCB9O1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQgPSBnZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQ7XG4vKipcbiAqIEF0dGVtcHQgdG8gcmV2ZWFsIHRoZSBlbGVtZW50IGZvciBhIHNvdXJjZSBsaW5lIGluIHRoZSBlZGl0b3IuXG4gKi9cbmZ1bmN0aW9uIHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKSB7XG4gICAgaWYgKCFzZXR0aW5nc18xLmdldFNldHRpbmdzKCkuc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobGluZSA8PSAwKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcbiAgICBpZiAoIXByZXZpb3VzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHNjcm9sbFRvID0gMDtcbiAgICBjb25zdCByZWN0ID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBwcmV2aW91c1RvcCA9IHJlY3QudG9wO1xuICAgIGlmIChuZXh0ICYmIG5leHQubGluZSAhPT0gcHJldmlvdXMubGluZSkge1xuICAgICAgICAvLyBCZXR3ZWVuIHR3byBlbGVtZW50cy4gR28gdG8gcGVyY2VudGFnZSBvZmZzZXQgYmV0d2VlbiB0aGVtLlxuICAgICAgICBjb25zdCBiZXR3ZWVuUHJvZ3Jlc3MgPSAobGluZSAtIHByZXZpb3VzLmxpbmUpIC8gKG5leHQubGluZSAtIHByZXZpb3VzLmxpbmUpO1xuICAgICAgICBjb25zdCBlbGVtZW50T2Zmc2V0ID0gbmV4dC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtIHByZXZpb3VzVG9wO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgYmV0d2VlblByb2dyZXNzICogZWxlbWVudE9mZnNldDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IHByb2dyZXNzSW5FbGVtZW50ID0gbGluZSAtIE1hdGguZmxvb3IobGluZSk7XG4gICAgICAgIHNjcm9sbFRvID0gcHJldmlvdXNUb3AgKyAocmVjdC5oZWlnaHQgKiBwcm9ncmVzc0luRWxlbWVudCk7XG4gICAgfVxuICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIE1hdGgubWF4KDEsIHdpbmRvdy5zY3JvbGxZICsgc2Nyb2xsVG8pKTtcbn1cbmV4cG9ydHMuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lID0gc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lO1xuZnVuY3Rpb24gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KSB7XG4gICAgY29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCk7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzQm91bmRzID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0RnJvbVByZXZpb3VzID0gKG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgaWYgKG5leHQpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb2dyZXNzQmV0d2VlbkVsZW1lbnRzID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c0JvdW5kcy50b3ApO1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IHByZXZpb3VzLmxpbmUgKyBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyAqIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc1dpdGhpbkVsZW1lbnQgPSBvZmZzZXRGcm9tUHJldmlvdXMgLyAocHJldmlvdXNCb3VuZHMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50O1xuICAgICAgICAgICAgcmV0dXJuIGNsYW1wTGluZShsaW5lKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmV4cG9ydHMuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQgPSBnZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldDtcbi8qKlxuICogVHJ5IHRvIGZpbmQgdGhlIGh0bWwgZWxlbWVudCBieSB1c2luZyBhIGZyYWdtZW50IGlkXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQoZnJhZ21lbnQpIHtcbiAgICByZXR1cm4gZ2V0Q29kZUxpbmVFbGVtZW50cygpLmZpbmQoKGVsZW1lbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuZWxlbWVudC5pZCA9PT0gZnJhZ21lbnQ7XG4gICAgfSk7XG59XG5leHBvcnRzLmdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQgPSBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxldCBjYWNoZWRTZXR0aW5ncyA9IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGdldERhdGEoa2V5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbmZ1bmN0aW9uIGdldFNldHRpbmdzKCkge1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U2V0dGluZ3MgPSBnZXRTZXR0aW5ncztcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsTUFBTTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUI7QUFDcEU7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QywyQ0FBMkM7QUFDdkY7QUFDQSxvREFBb0QsaUJBQWlCO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxPQUFPO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7Ozs7Ozs7Ozs7Ozs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLGtDQUFrQztBQUMzRDtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMseUJBQXlCO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsaUJBQWlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLGlCQUFpQjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUN2SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxJQUFJO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSBcIi4vcHJldmlldy1zcmMvaW5kZXgudHNcIik7XG4iLCIvKipcbiAqIGxvZGFzaCAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIG1vZHVsYXJpemUgZXhwb3J0cz1cIm5wbVwiIC1vIC4vYFxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnMgPGh0dHBzOi8vanF1ZXJ5Lm9yZy8+XG4gKiBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9sb2Rhc2guY29tL2xpY2Vuc2U+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuOC4zIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4gKi9cblxuLyoqIFVzZWQgYXMgdGhlIGBUeXBlRXJyb3JgIG1lc3NhZ2UgZm9yIFwiRnVuY3Rpb25zXCIgbWV0aG9kcy4gKi9cbnZhciBGVU5DX0VSUk9SX1RFWFQgPSAnRXhwZWN0ZWQgYSBmdW5jdGlvbic7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIE5BTiA9IDAgLyAwO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UuICovXG52YXIgcmVUcmltID0gL15cXHMrfFxccyskL2c7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JhZEhleCA9IC9eWy0rXTB4WzAtOWEtZl0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmluYXJ5IHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG9jdGFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc09jdGFsID0gL14wb1swLTddKyQvaTtcblxuLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbnZhciBmcmVlUGFyc2VJbnQgPSBwYXJzZUludDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbnZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluO1xuXG4vKipcbiAqIEdldHMgdGhlIHRpbWVzdGFtcCBvZiB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZVxuICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAyLjQuMFxuICogQGNhdGVnb3J5IERhdGVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVzdGFtcC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5kZWZlcihmdW5jdGlvbihzdGFtcCkge1xuICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICogfSwgXy5ub3coKSk7XG4gKiAvLyA9PiBMb2dzIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGl0IHRvb2sgZm9yIHRoZSBkZWZlcnJlZCBpbnZvY2F0aW9uLlxuICovXG52YXIgbm93ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiByb290LkRhdGUubm93KCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gKiBpbnZva2VkLiBUaGUgZGVib3VuY2VkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYCBtZXRob2QgdG8gY2FuY2VsXG4gKiBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0byBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS5cbiAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICogbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICogd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbi4gU3Vic2VxdWVudFxuICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAqIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8uZGVib3VuY2VgIGFuZCBgXy50aHJvdHRsZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XVxuICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXguXG4gKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICpcbiAqIC8vIEludm9rZSBgc2VuZE1haWxgIHdoZW4gY2xpY2tlZCwgZGVib3VuY2luZyBzdWJzZXF1ZW50IGNhbGxzLlxuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICogICAnbGVhZGluZyc6IHRydWUsXG4gKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gKiB9KSk7XG4gKlxuICogLy8gRW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxscy5cbiAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICogdmFyIHNvdXJjZSA9IG5ldyBFdmVudFNvdXJjZSgnL3N0cmVhbScpO1xuICogalF1ZXJ5KHNvdXJjZSkub24oJ21lc3NhZ2UnLCBkZWJvdW5jZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGFzdEFyZ3MsXG4gICAgICBsYXN0VGhpcyxcbiAgICAgIG1heFdhaXQsXG4gICAgICByZXN1bHQsXG4gICAgICB0aW1lcklkLFxuICAgICAgbGFzdENhbGxUaW1lLFxuICAgICAgbGFzdEludm9rZVRpbWUgPSAwLFxuICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgbWF4aW5nID0gZmFsc2UsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICBtYXhXYWl0ID0gbWF4aW5nID8gbmF0aXZlTWF4KHRvTnVtYmVyKG9wdGlvbnMubWF4V2FpdCkgfHwgMCwgd2FpdCkgOiBtYXhXYWl0O1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cblxuICBmdW5jdGlvbiBpbnZva2VGdW5jKHRpbWUpIHtcbiAgICB2YXIgYXJncyA9IGxhc3RBcmdzLFxuICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgLy8gUmVzZXQgYW55IGBtYXhXYWl0YCB0aW1lci5cbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbWFpbmluZ1dhaXQodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWUsXG4gICAgICAgIHJlc3VsdCA9IHdhaXQgLSB0aW1lU2luY2VMYXN0Q2FsbDtcblxuICAgIHJldHVybiBtYXhpbmcgPyBuYXRpdmVNaW4ocmVzdWx0LCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBzaG91bGRJbnZva2UodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWU7XG5cbiAgICAvLyBFaXRoZXIgdGhpcyBpcyB0aGUgZmlyc3QgY2FsbCwgYWN0aXZpdHkgaGFzIHN0b3BwZWQgYW5kIHdlJ3JlIGF0IHRoZVxuICAgIC8vIHRyYWlsaW5nIGVkZ2UsIHRoZSBzeXN0ZW0gdGltZSBoYXMgZ29uZSBiYWNrd2FyZHMgYW5kIHdlJ3JlIHRyZWF0aW5nXG4gICAgLy8gaXQgYXMgdGhlIHRyYWlsaW5nIGVkZ2UsIG9yIHdlJ3ZlIGhpdCB0aGUgYG1heFdhaXRgIGxpbWl0LlxuICAgIHJldHVybiAobGFzdENhbGxUaW1lID09PSB1bmRlZmluZWQgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXJFeHBpcmVkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCk7XG4gICAgaWYgKHNob3VsZEludm9rZSh0aW1lKSkge1xuICAgICAgcmV0dXJuIHRyYWlsaW5nRWRnZSh0aW1lKTtcbiAgICB9XG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYWlsaW5nRWRnZSh0aW1lKSB7XG4gICAgdGltZXJJZCA9IHVuZGVmaW5lZDtcblxuICAgIC8vIE9ubHkgaW52b2tlIGlmIHdlIGhhdmUgYGxhc3RBcmdzYCB3aGljaCBtZWFucyBgZnVuY2AgaGFzIGJlZW5cbiAgICAvLyBkZWJvdW5jZWQgYXQgbGVhc3Qgb25jZS5cbiAgICBpZiAodHJhaWxpbmcgJiYgbGFzdEFyZ3MpIHtcbiAgICAgIHJldHVybiBpbnZva2VGdW5jKHRpbWUpO1xuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgaWYgKHRpbWVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDA7XG4gICAgbGFzdEFyZ3MgPSBsYXN0Q2FsbFRpbWUgPSBsYXN0VGhpcyA9IHRpbWVySWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICByZXR1cm4gdGltZXJJZCA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKG5vdygpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpLFxuICAgICAgICBpc0ludm9raW5nID0gc2hvdWxkSW52b2tlKHRpbWUpO1xuXG4gICAgbGFzdEFyZ3MgPSBhcmd1bWVudHM7XG4gICAgbGFzdFRoaXMgPSB0aGlzO1xuICAgIGxhc3RDYWxsVGltZSA9IHRpbWU7XG5cbiAgICBpZiAoaXNJbnZva2luZykge1xuICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICAgIGlmIChtYXhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIGludm9jYXRpb25zIGluIGEgdGlnaHQgbG9vcC5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgcmV0dXJuIGludm9rZUZ1bmMobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBkZWJvdW5jZWQuY2FuY2VsID0gY2FuY2VsO1xuICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgcmV0dXJuIGRlYm91bmNlZDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgdGhyb3R0bGVkIGZ1bmN0aW9uIHRoYXQgb25seSBpbnZva2VzIGBmdW5jYCBhdCBtb3N0IG9uY2UgcGVyXG4gKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICogbWV0aG9kIHRvIGNhbmNlbCBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0b1xuICogaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgXG4gKiBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgXG4gKiB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWQgd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlXG4gKiB0aHJvdHRsZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnQgY2FsbHMgdG8gdGhlIHRocm90dGxlZCBmdW5jdGlvbiByZXR1cm4gdGhlXG4gKiByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8udGhyb3R0bGVgIGFuZCBgXy5kZWJvdW5jZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBpbnZvY2F0aW9ucyB0by5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB0aHJvdHRsZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGV4Y2Vzc2l2ZWx5IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBzY3JvbGxpbmcuXG4gKiBqUXVlcnkod2luZG93KS5vbignc2Nyb2xsJywgXy50aHJvdHRsZSh1cGRhdGVQb3NpdGlvbiwgMTAwKSk7XG4gKlxuICogLy8gSW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXMuXG4gKiB2YXIgdGhyb3R0bGVkID0gXy50aHJvdHRsZShyZW5ld1Rva2VuLCAzMDAwMDAsIHsgJ3RyYWlsaW5nJzogZmFsc2UgfSk7XG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdGhyb3R0bGVkKTtcbiAqXG4gKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIHRocm90dGxlZCBpbnZvY2F0aW9uLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgdGhyb3R0bGVkLmNhbmNlbCk7XG4gKi9cbmZ1bmN0aW9uIHRocm90dGxlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgdmFyIGxlYWRpbmcgPSB0cnVlLFxuICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICB9XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAnbGVhZGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy5sZWFkaW5nIDogbGVhZGluZztcbiAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICB9XG4gIHJldHVybiBkZWJvdW5jZShmdW5jLCB3YWl0LCB7XG4gICAgJ2xlYWRpbmcnOiBsZWFkaW5nLFxuICAgICdtYXhXYWl0Jzogd2FpdCxcbiAgICAndHJhaWxpbmcnOiB0cmFpbGluZ1xuICB9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAhIXZhbHVlICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdExpa2Uoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgcmV0dXJuICEhdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3ltYm9sLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNTeW1ib2woU3ltYm9sLml0ZXJhdG9yKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzU3ltYm9sKCdhYmMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N5bWJvbCcgfHxcbiAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBudW1iZXIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8udG9OdW1iZXIoMy4yKTtcbiAqIC8vID0+IDMuMlxuICpcbiAqIF8udG9OdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gKiAvLyA9PiA1ZS0zMjRcbiAqXG4gKiBfLnRvTnVtYmVyKEluZmluaXR5KTtcbiAqIC8vID0+IEluZmluaXR5XG4gKlxuICogXy50b051bWJlcignMy4yJyk7XG4gKiAvLyA9PiAzLjJcbiAqL1xuZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgcmV0dXJuIE5BTjtcbiAgfVxuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgdmFyIG90aGVyID0gdHlwZW9mIHZhbHVlLnZhbHVlT2YgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgIHZhbHVlID0gaXNPYmplY3Qob3RoZXIpID8gKG90aGVyICsgJycpIDogb3RoZXI7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogK3ZhbHVlO1xuICB9XG4gIHZhbHVlID0gdmFsdWUucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgcmV0dXJuIChpc0JpbmFyeSB8fCByZUlzT2N0YWwudGVzdCh2YWx1ZSkpXG4gICAgPyBmcmVlUGFyc2VJbnQodmFsdWUuc2xpY2UoMiksIGlzQmluYXJ5ID8gMiA6IDgpXG4gICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdGhyb3R0bGU7XG4iLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSwgZXZhbCkoXCJ0aGlzXCIpO1xyXG59IGNhdGNoIChlKSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcclxuXHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIikgZyA9IHdpbmRvdztcclxufVxyXG5cclxuLy8gZyBjYW4gc3RpbGwgYmUgdW5kZWZpbmVkLCBidXQgbm90aGluZyB0byBkbyBhYm91dCBpdC4uLlxyXG4vLyBXZSByZXR1cm4gdW5kZWZpbmVkLCBpbnN0ZWFkIG9mIG5vdGhpbmcgaGVyZSwgc28gaXQnc1xyXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGc7XHJcbiIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5jb25zdCBzY3JvbGxfc3luY18xID0gcmVxdWlyZShcIi4vc2Nyb2xsLXN5bmNcIik7XG5jbGFzcyBBY3RpdmVMaW5lTWFya2VyIHtcbiAgICBvbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24obGluZSkge1xuICAgICAgICBjb25zdCB7IHByZXZpb3VzIH0gPSBzY3JvbGxfc3luY18xLmdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKHByZXZpb3VzICYmIHByZXZpb3VzLmVsZW1lbnQpO1xuICAgIH1cbiAgICBfdXBkYXRlKGJlZm9yZSkge1xuICAgICAgICB0aGlzLl91bm1hcmtBY3RpdmVFbGVtZW50KHRoaXMuX2N1cnJlbnQpO1xuICAgICAgICB0aGlzLl9tYXJrQWN0aXZlRWxlbWVudChiZWZvcmUpO1xuICAgICAgICB0aGlzLl9jdXJyZW50ID0gYmVmb3JlO1xuICAgIH1cbiAgICBfdW5tYXJrQWN0aXZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUucmVwbGFjZSgvXFxiY29kZS1hY3RpdmUtbGluZVxcYi9nLCAnJyk7XG4gICAgfVxuICAgIF9tYXJrQWN0aXZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lICs9ICcgY29kZS1hY3RpdmUtbGluZSc7XG4gICAgfVxufVxuZXhwb3J0cy5BY3RpdmVMaW5lTWFya2VyID0gQWN0aXZlTGluZU1hcmtlcjtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiBvbmNlRG9jdW1lbnRMb2FkZWQoZikge1xuICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ3VuaW5pdGlhbGl6ZWQnKSB7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGYoKTtcbiAgICB9XG59XG5leHBvcnRzLm9uY2VEb2N1bWVudExvYWRlZCA9IG9uY2VEb2N1bWVudExvYWRlZDtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBhY3RpdmVMaW5lTWFya2VyXzEgPSByZXF1aXJlKFwiLi9hY3RpdmVMaW5lTWFya2VyXCIpO1xuY29uc3QgZXZlbnRzXzEgPSByZXF1aXJlKFwiLi9ldmVudHNcIik7XG5jb25zdCBtZXNzYWdpbmdfMSA9IHJlcXVpcmUoXCIuL21lc3NhZ2luZ1wiKTtcbmNvbnN0IHNjcm9sbF9zeW5jXzEgPSByZXF1aXJlKFwiLi9zY3JvbGwtc3luY1wiKTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmNvbnN0IHRocm90dGxlID0gcmVxdWlyZShcImxvZGFzaC50aHJvdHRsZVwiKTtcbmxldCBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG5jb25zdCBtYXJrZXIgPSBuZXcgYWN0aXZlTGluZU1hcmtlcl8xLkFjdGl2ZUxpbmVNYXJrZXIoKTtcbmNvbnN0IHNldHRpbmdzID0gc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpO1xuY29uc3QgdnNjb2RlID0gYWNxdWlyZVZzQ29kZUFwaSgpO1xuLy8gU2V0IFZTIENvZGUgc3RhdGVcbmxldCBzdGF0ZSA9IHNldHRpbmdzXzEuZ2V0RGF0YSgnZGF0YS1zdGF0ZScpO1xudnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcbmNvbnN0IG1lc3NhZ2luZyA9IG1lc3NhZ2luZ18xLmNyZWF0ZVBvc3RlckZvclZzQ29kZSh2c2NvZGUpO1xud2luZG93LmNzcEFsZXJ0ZXIuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG53aW5kb3cuc3R5bGVMb2FkaW5nTW9uaXRvci5zZXRQb3N0ZXIobWVzc2FnaW5nKTtcbndpbmRvdy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgdXBkYXRlSW1hZ2VTaXplcygpO1xufTtcbmV2ZW50c18xLm9uY2VEb2N1bWVudExvYWRlZCgoKSA9PiB7XG4gICAgaWYgKHNldHRpbmdzLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgLy8gVHJ5IHRvIHNjcm9sbCB0byBmcmFnbWVudCBpZiBhdmFpbGFibGVcbiAgICAgICAgICAgIGlmIChzdGF0ZS5mcmFnbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBzY3JvbGxfc3luY18xLmdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQoc3RhdGUuZnJhZ21lbnQpO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUoZWxlbWVudC5saW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbml0aWFsTGluZSA9ICtzZXR0aW5ncy5saW5lO1xuICAgICAgICAgICAgICAgIGlmICghaXNOYU4oaW5pdGlhbExpbmUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUoaW5pdGlhbExpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgMCk7XG4gICAgfVxufSk7XG5jb25zdCBvblVwZGF0ZVZpZXcgPSAoKCkgPT4ge1xuICAgIGNvbnN0IGRvU2Nyb2xsID0gdGhyb3R0bGUoKGxpbmUpID0+IHtcbiAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKTtcbiAgICB9LCA1MCk7XG4gICAgcmV0dXJuIChsaW5lLCBzZXR0aW5ncykgPT4ge1xuICAgICAgICBpZiAoIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgICAgICBzZXR0aW5ncy5saW5lID0gbGluZTtcbiAgICAgICAgICAgIGRvU2Nyb2xsKGxpbmUpO1xuICAgICAgICB9XG4gICAgfTtcbn0pKCk7XG5sZXQgdXBkYXRlSW1hZ2VTaXplcyA9IHRocm90dGxlKCgpID0+IHtcbiAgICBjb25zdCBpbWFnZUluZm8gPSBbXTtcbiAgICBsZXQgaW1hZ2VzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2ltZycpO1xuICAgIGlmIChpbWFnZXMpIHtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGltZyA9IGltYWdlc1tpXTtcbiAgICAgICAgICAgIGlmIChpbWcuY2xhc3NMaXN0LmNvbnRhaW5zKCdsb2FkaW5nJykpIHtcbiAgICAgICAgICAgICAgICBpbWcuY2xhc3NMaXN0LnJlbW92ZSgnbG9hZGluZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW1hZ2VJbmZvLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBpbWcuaWQsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpbWcuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBpbWcud2lkdGhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnY2FjaGVJbWFnZVNpemVzJywgaW1hZ2VJbmZvKTtcbiAgICB9XG59LCA1MCk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgKCkgPT4ge1xuICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICB1cGRhdGVJbWFnZVNpemVzKCk7XG59LCB0cnVlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZXZlbnQgPT4ge1xuICAgIGlmIChldmVudC5kYXRhLnNvdXJjZSAhPT0gc2V0dGluZ3Muc291cmNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoIChldmVudC5kYXRhLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnb25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uJzpcbiAgICAgICAgICAgIG1hcmtlci5vbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24oZXZlbnQuZGF0YS5saW5lKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1cGRhdGVWaWV3JzpcbiAgICAgICAgICAgIG9uVXBkYXRlVmlldyhldmVudC5kYXRhLmxpbmUsIHNldHRpbmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbn0sIGZhbHNlKTtcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgZXZlbnQgPT4ge1xuICAgIGlmICghc2V0dGluZ3MuZG91YmxlQ2xpY2tUb1N3aXRjaFRvRWRpdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gSWdub3JlIGNsaWNrcyBvbiBsaW5rc1xuICAgIGZvciAobGV0IG5vZGUgPSBldmVudC50YXJnZXQ7IG5vZGU7IG5vZGUgPSBub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUudGFnTmFtZSA9PT0gJ0EnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgb2Zmc2V0ID0gZXZlbnQucGFnZVk7XG4gICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KTtcbiAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2RpZENsaWNrJywgeyBsaW5lOiBNYXRoLmZsb29yKGxpbmUpIH0pO1xuICAgIH1cbn0pO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBldmVudCA9PiB7XG4gICAgaWYgKCFldmVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBub2RlID0gZXZlbnQudGFyZ2V0O1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgIGlmIChub2RlLnRhZ05hbWUgJiYgbm9kZS50YWdOYW1lID09PSAnQScgJiYgbm9kZS5ocmVmKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKS5zdGFydHNXaXRoKCcjJykpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub2RlLmhyZWYuc3RhcnRzV2l0aCgnZmlsZTovLycpIHx8IG5vZGUuaHJlZi5zdGFydHNXaXRoKCd2c2NvZGUtcmVzb3VyY2U6JykgfHwgbm9kZS5ocmVmLnN0YXJ0c1dpdGgoc2V0dGluZ3Mud2Vidmlld1Jlc291cmNlUm9vdCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBbcGF0aCwgZnJhZ21lbnRdID0gbm9kZS5ocmVmXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eZmlsZTpcXC9cXC8vaSwgJycpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9ednNjb2RlLXJlc291cmNlOlxcL1xcL1teXFwvXStcXC8vaSwgJycpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4ke2VzY2FwZVJlZ0V4cChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KX1gKSlcbiAgICAgICAgICAgICAgICAgICAgLnNwbGl0KCcjJyk7XG4gICAgICAgICAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjbGlja0xpbmsnLCB7IHBhdGgsIGZyYWdtZW50IH0pO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgIH1cbn0sIHRydWUpO1xuaWYgKHNldHRpbmdzLnNjcm9sbEVkaXRvcldpdGhQcmV2aWV3KSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRocm90dGxlKCgpID0+IHtcbiAgICAgICAgaWYgKHNjcm9sbERpc2FibGVkKSB7XG4gICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ3JldmVhbExpbmUnLCB7IGxpbmUgfSk7XG4gICAgICAgICAgICAgICAgc3RhdGUubGluZSA9IGxpbmU7XG4gICAgICAgICAgICAgICAgdnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIDUwKSk7XG59XG5mdW5jdGlvbiBlc2NhcGVSZWdFeHAodGV4dCkge1xuICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL1stW1xcXXt9KCkqKz8uLFxcXFxeJHwjXFxzXS9nLCAnXFxcXCQmJyk7XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuZXhwb3J0cy5jcmVhdGVQb3N0ZXJGb3JWc0NvZGUgPSAodnNjb2RlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBjbGFzcyB7XG4gICAgICAgIHBvc3RNZXNzYWdlKHR5cGUsIGJvZHkpIHtcbiAgICAgICAgICAgIHZzY29kZS5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICBzb3VyY2U6IHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKS5zb3VyY2UsXG4gICAgICAgICAgICAgICAgYm9keVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5mdW5jdGlvbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpIHtcbiAgICByZXR1cm4gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIHZhbHVlKSk7XG59XG5mdW5jdGlvbiBjbGFtcExpbmUobGluZSkge1xuICAgIHJldHVybiBjbGFtcCgwLCBzZXR0aW5nc18xLmdldFNldHRpbmdzKCkubGluZUNvdW50IC0gMSwgbGluZSk7XG59XG5jb25zdCBnZXRDb2RlTGluZUVsZW1lbnRzID0gKCgpID0+IHtcbiAgICBsZXQgZWxlbWVudHM7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgaWYgKCFlbGVtZW50cykge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBbeyBlbGVtZW50OiBkb2N1bWVudC5ib2R5LCBsaW5lOiAwIH1dO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2NvZGUtbGluZScpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGluZSA9ICtlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1saW5lJyk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50cy5wdXNoKHsgZWxlbWVudDogZWxlbWVudCwgbGluZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsZW1lbnRzO1xuICAgIH07XG59KSgpO1xuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgbWFwIHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxpbmUgaW4gdGhlIGVkaXRvci5cbiAqXG4gKiBJZiBhbiBleGFjdCBtYXRjaCwgcmV0dXJucyBhIHNpbmdsZSBlbGVtZW50LiBJZiB0aGUgbGluZSBpcyBiZXR3ZWVuIGVsZW1lbnRzLFxuICogcmV0dXJucyB0aGUgZWxlbWVudCBwcmlvciB0byBhbmQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGdpdmVuIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGdldEVsZW1lbnRzRm9yU291cmNlTGluZSh0YXJnZXRMaW5lKSB7XG4gICAgY29uc3QgbGluZU51bWJlciA9IE1hdGguZmxvb3IodGFyZ2V0TGluZSk7XG4gICAgY29uc3QgbGluZXMgPSBnZXRDb2RlTGluZUVsZW1lbnRzKCk7XG4gICAgbGV0IHByZXZpb3VzID0gbGluZXNbMF0gfHwgbnVsbDtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGxpbmVzKSB7XG4gICAgICAgIGlmIChlbnRyeS5saW5lID09PSBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91czogZW50cnksIG5leHQ6IHVuZGVmaW5lZCB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGVudHJ5LmxpbmUgPiBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91cywgbmV4dDogZW50cnkgfTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2aW91cyA9IGVudHJ5O1xuICAgIH1cbiAgICByZXR1cm4geyBwcmV2aW91cyB9O1xufVxuZXhwb3J0cy5nZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUgPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmU7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBhcmUgYXQgYSBzcGVjaWZpYyBwaXhlbCBvZmZzZXQgb24gdGhlIHBhZ2UuXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpIHtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBjb25zdCBwb3NpdGlvbiA9IG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZO1xuICAgIGxldCBsbyA9IC0xO1xuICAgIGxldCBoaSA9IGxpbmVzLmxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKGxvICsgMSA8IGhpKSB7XG4gICAgICAgIGNvbnN0IG1pZCA9IE1hdGguZmxvb3IoKGxvICsgaGkpIC8gMik7XG4gICAgICAgIGNvbnN0IGJvdW5kcyA9IGxpbmVzW21pZF0uZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaWYgKGJvdW5kcy50b3AgKyBib3VuZHMuaGVpZ2h0ID49IHBvc2l0aW9uKSB7XG4gICAgICAgICAgICBoaSA9IG1pZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxvID0gbWlkO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGhpRWxlbWVudCA9IGxpbmVzW2hpXTtcbiAgICBjb25zdCBoaUJvdW5kcyA9IGhpRWxlbWVudC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChoaSA+PSAxICYmIGhpQm91bmRzLnRvcCA+IHBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IGxvRWxlbWVudCA9IGxpbmVzW2xvXTtcbiAgICAgICAgcmV0dXJuIHsgcHJldmlvdXM6IGxvRWxlbWVudCwgbmV4dDogaGlFbGVtZW50IH07XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzOiBoaUVsZW1lbnQgfTtcbn1cbmV4cG9ydHMuZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0O1xuLyoqXG4gKiBBdHRlbXB0IHRvIHJldmVhbCB0aGUgZWxlbWVudCBmb3IgYSBzb3VyY2UgbGluZSBpbiB0aGUgZWRpdG9yLlxuICovXG5mdW5jdGlvbiBzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSkge1xuICAgIGlmICghc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGxpbmUgPD0gMCkge1xuICAgICAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB7IHByZXZpb3VzLCBuZXh0IH0gPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG4gICAgaWYgKCFwcmV2aW91cykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBzY3JvbGxUbyA9IDA7XG4gICAgY29uc3QgcmVjdCA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgcHJldmlvdXNUb3AgPSByZWN0LnRvcDtcbiAgICBpZiAobmV4dCAmJiBuZXh0LmxpbmUgIT09IHByZXZpb3VzLmxpbmUpIHtcbiAgICAgICAgLy8gQmV0d2VlbiB0d28gZWxlbWVudHMuIEdvIHRvIHBlcmNlbnRhZ2Ugb2Zmc2V0IGJldHdlZW4gdGhlbS5cbiAgICAgICAgY29uc3QgYmV0d2VlblByb2dyZXNzID0gKGxpbmUgLSBwcmV2aW91cy5saW5lKSAvIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgY29uc3QgZWxlbWVudE9mZnNldCA9IG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c1RvcDtcbiAgICAgICAgc2Nyb2xsVG8gPSBwcmV2aW91c1RvcCArIGJldHdlZW5Qcm9ncmVzcyAqIGVsZW1lbnRPZmZzZXQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBwcm9ncmVzc0luRWxlbWVudCA9IGxpbmUgLSBNYXRoLmZsb29yKGxpbmUpO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgKHJlY3QuaGVpZ2h0ICogcHJvZ3Jlc3NJbkVsZW1lbnQpO1xuICAgIH1cbiAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCBNYXRoLm1heCgxLCB3aW5kb3cuc2Nyb2xsWSArIHNjcm9sbFRvKSk7XG59XG5leHBvcnRzLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZSA9IHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZTtcbmZ1bmN0aW9uIGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpO1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICBjb25zdCBwcmV2aW91c0JvdW5kcyA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IG9mZnNldEZyb21QcmV2aW91cyA9IChvZmZzZXQgLSB3aW5kb3cuc2Nyb2xsWSAtIHByZXZpb3VzQm91bmRzLnRvcCk7XG4gICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyA9IG9mZnNldEZyb21QcmV2aW91cyAvIChuZXh0LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NCZXR3ZWVuRWxlbWVudHMgKiAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG4gICAgICAgICAgICByZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50ID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKHByZXZpb3VzQm91bmRzLmhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gcHJldmlvdXMubGluZSArIHByb2dyZXNzV2l0aGluRWxlbWVudDtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5leHBvcnRzLmdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0ID0gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQ7XG4vKipcbiAqIFRyeSB0byBmaW5kIHRoZSBodG1sIGVsZW1lbnQgYnkgdXNpbmcgYSBmcmFnbWVudCBpZFxuICovXG5mdW5jdGlvbiBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50KGZyYWdtZW50KSB7XG4gICAgcmV0dXJuIGdldENvZGVMaW5lRWxlbWVudHMoKS5maW5kKChlbGVtZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBlbGVtZW50LmVsZW1lbnQuaWQgPT09IGZyYWdtZW50O1xuICAgIH0pO1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudEZvckZyYWdtZW50ID0gZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudDtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sZXQgY2FjaGVkU2V0dGluZ3MgPSB1bmRlZmluZWQ7XG5mdW5jdGlvbiBnZXREYXRhKGtleSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndnNjb2RlLW1hcmtkb3duLXByZXZpZXctZGF0YScpO1xuICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBkYXRhIGZvciAke2tleX1gKTtcbn1cbmV4cG9ydHMuZ2V0RGF0YSA9IGdldERhdGE7XG5mdW5jdGlvbiBnZXRTZXR0aW5ncygpIHtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICBjYWNoZWRTZXR0aW5ncyA9IGdldERhdGEoJ2RhdGEtc2V0dGluZ3MnKTtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHNldHRpbmdzJyk7XG59XG5leHBvcnRzLmdldFNldHRpbmdzID0gZ2V0U2V0dGluZ3M7XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/extensions/markdown-language-features/preview-src/index.ts b/extensions/markdown-language-features/preview-src/index.ts index b12614fe9ec..dcf46940aea 100644 --- a/extensions/markdown-language-features/preview-src/index.ts +++ b/extensions/markdown-language-features/preview-src/index.ts @@ -141,7 +141,11 @@ document.addEventListener('click', event => { break; } if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { - const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)).split('#'); + const [path, fragment] = node.href + .replace(/^file:\/\//i, '') + .replace(/^vscode-resource:\/\/[^\/]+\//i, '') + .replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)) + .split('#'); messaging.postMessage('clickLink', { path, fragment }); event.preventDefault(); event.stopPropagation(); From d91209b3563fa386c31d023b2e54b2f636caf550 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 14:13:01 -0700 Subject: [PATCH 119/435] Fix image views not being activated properly --- src/vs/workbench/contrib/customEditor/browser/customEditors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 347a5eb3164..438566bb925 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -175,7 +175,7 @@ export class CustomEditorService implements ICustomEditorService { const existingEditors = group.editors.filter(editor => editor.getResource() && isEqual(editor.getResource()!, resource)); if (existingEditors.length) { const existing = existingEditors[0]; - if (existing.matches(input)) { + if (input.matches(existing)) { return; } From b8869cd9891e6653e2b8ca01e679d20e705f452c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 14:19:29 -0700 Subject: [PATCH 120/435] Fix git diff view for untracked image files showing an error on left side --- extensions/image-preview/src/preview.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 2eb566281c5..89e60097942 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -136,7 +136,7 @@ export class Preview extends Disposable { - + @@ -153,6 +153,8 @@ export class Preview extends Disposable { return encodeURI(resource.toString(true)); case 'git': + // Show blank image + return encodeURI('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42gEFAPr/AP///wAI/AL+Sr4t6gAAAABJRU5ErkJggg=='); default: From 2cf9921ee52b6d602a48dce1d5ebdacdd37bcf6b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 14:30:35 -0700 Subject: [PATCH 121/435] Fixing name and description for custom editor on data uris --- .../customEditor/browser/customEditorInput.ts | 27 +++++++++++++++---- .../webview/browser/webviewEditorInput.ts | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index b5e56ab7456..7af6673ed7b 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -7,7 +7,7 @@ import { memoize } from 'vs/base/common/decorators'; import { Emitter } from 'vs/base/common/event'; import { UnownedDisposable } from 'vs/base/common/lifecycle'; import { basename } from 'vs/base/common/path'; -import { isEqual } from 'vs/base/common/resources'; +import { isEqual, DataUri } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { WebviewContentState } from 'vs/editor/common/modes'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -18,12 +18,12 @@ import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webvi import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; import { promptSave } from 'vs/workbench/services/textfile/browser/textFileService'; +import { Schemas } from 'vs/base/common/network'; export class CustomFileEditorInput extends WebviewInput { public static typeId = 'workbench.editors.webviewEditor'; - private name?: string; private _hasResolved = false; private readonly _editorResource: URI; private _state = WebviewContentState.Readonly; @@ -49,11 +49,28 @@ export class CustomFileEditorInput extends WebviewInput { return this._editorResource; } + @memoize getName(): string { - if (!this.name) { - this.name = basename(this.labelService.getUriLabel(this.getResource())); + if (this.getResource().scheme === Schemas.data) { + const metadata = DataUri.parseMetaData(this.getResource()); + const label = metadata.get(DataUri.META_DATA_LABEL); + if (typeof label === 'string') { + return label; + } } - return this.name; + return basename(this.labelService.getUriLabel(this.getResource())); + } + + @memoize + getDescription(): string | undefined { + if (this.getResource().scheme === Schemas.data) { + const metadata = DataUri.parseMetaData(this.getResource()); + const description = metadata.get(DataUri.META_DATA_DESCRIPTION); + if (typeof description === 'string') { + return description; + } + } + return super.getDescription(); } matches(other: IEditorInput): boolean { diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index ee87e913ab7..4980730a177 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -94,7 +94,7 @@ export class WebviewInput extends EditorInput { return this.getName(); } - public getDescription() { + public getDescription(): string | undefined { return undefined; } From 615e262789c3f1872758c119a095254fa5316ad7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 14:46:18 -0700 Subject: [PATCH 122/435] Fix git smoke tests --- test/automation/src/scm.ts | 2 +- test/smoke/src/areas/git/git.test.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/automation/src/scm.ts b/test/automation/src/scm.ts index 519faddb27c..2f56e31a87c 100644 --- a/test/automation/src/scm.ts +++ b/test/automation/src/scm.ts @@ -9,7 +9,7 @@ import { findElement, findElements, Code } from './code'; const VIEWLET = 'div[id="workbench.view.scm"]'; const SCM_INPUT = `${VIEWLET} .scm-editor textarea`; -const SCM_RESOURCE = `${VIEWLET} .monaco-list-row > .resource`; +const SCM_RESOURCE = `${VIEWLET} .monaco-list-row .resource`; const REFRESH_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Refresh"]`; const COMMIT_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Commit"]`; const SCM_RESOURCE_CLICK = (name: string) => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .label-name`; diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 300c832694d..a23a4f3080b 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -13,6 +13,7 @@ export function setup() { describe('Git', () => { before(async function () { const app = this.app as Application; + await app.workbench.settingsEditor.addUserSetting('scm.defaultViewMode', '"list"'); cp.execSync('git config user.name testuser', { cwd: app.workspacePathOrFolder }); cp.execSync('git config user.email monacotools@microsoft.com', { cwd: app.workspacePathOrFolder }); From d84015cc4dbbca2d83ffe4b1dc60981f2e175b6f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 15:18:21 -0700 Subject: [PATCH 123/435] Change event name to type --- src/vs/platform/diagnostics/node/diagnosticsService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/diagnostics/node/diagnosticsService.ts b/src/vs/platform/diagnostics/node/diagnosticsService.ts index 0a5469df8eb..461bcf07744 100644 --- a/src/vs/platform/diagnostics/node/diagnosticsService.ts +++ b/src/vs/platform/diagnostics/node/diagnosticsService.ts @@ -551,32 +551,32 @@ export class DiagnosticsService implements IDiagnosticsService { }); type WorkspaceStatsFileClassification = { rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - name: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; + type: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; count: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; }; type WorkspaceStatsFileEvent = { rendererSessionId: string; - name: string; + type: string; count: number; }; stats.fileTypes.forEach(e => { this.telemetryService.publicLog2('workspace.stats.file', { rendererSessionId: workspace.rendererSessionId, - name: e.name, + type: e.name, count: e.count }); }); stats.launchConfigFiles.forEach(e => { this.telemetryService.publicLog2('workspace.stats.launchConfigFile', { rendererSessionId: workspace.rendererSessionId, - name: e.name, + type: e.name, count: e.count }); }); stats.configFiles.forEach(e => { this.telemetryService.publicLog2('workspace.stats.configFiles', { rendererSessionId: workspace.rendererSessionId, - name: e.name, + type: e.name, count: e.count }); }); From f137abf254370ef7edab733e9922553c07da6305 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 2 Oct 2019 16:14:14 -0700 Subject: [PATCH 124/435] Update distro, fix web smoke test folder --- package.json | 2 +- test/automation/src/puppeteerDriver.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c7d711adb1d..74a9dd79abe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "e8ae0d57bfb843f8df1eb8d78aa894bd2b72e7f9", + "distro": "516ad9e2679fb5f8a9d91bafcdc9d4d2f6005dfd", "author": { "name": "Microsoft Corporation" }, diff --git a/test/automation/src/puppeteerDriver.ts b/test/automation/src/puppeteerDriver.ts index ceb76add39c..40fd699b6d3 100644 --- a/test/automation/src/puppeteerDriver.ts +++ b/test/automation/src/puppeteerDriver.ts @@ -92,9 +92,17 @@ let endpoint: string | undefined; export async function launch(_args: string[]): Promise { args = _args; - const webUserDataDir = args.filter(e => e.includes('--user-data-dir='))[0].replace('--user-data-dir=', ''); - await promisify(mkdir)(webUserDataDir); - server = spawn(join(args[0], `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`), ['--browser', 'none', '--driver', 'web', '--web-user-data-dir', webUserDataDir]); + const agentFolder = args.filter(e => e.includes('--user-data-dir='))[0].replace('--user-data-dir=', ''); + await promisify(mkdir)(agentFolder); + const env = { + VSCODE_AGENT_FOLDER: agentFolder, + ...process.env + }; + server = spawn( + join(args[0], `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`), + ['--browser', 'none', '--driver', 'web'], + { env } + ); server.stderr.on('data', e => console.log('Server stderr: ' + e)); server.stdout.on('data', e => console.log('Server stdout: ' + e)); process.on('exit', teardown); From 10309701ff601bcb51a8912d99036588d5cff9b4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 18:17:27 -0700 Subject: [PATCH 125/435] Don't show webview overlay by default If there is an error while resolving the webview itself, this invisible container can end sticking around incorrectly until the input it destoryed. Better to make sure it is hidden so that it doesn't block user input --- .../contrib/webview/browser/dynamicWebviewEditorOverlay.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index e052f0cccaa..77dbfb2c41a 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -47,6 +47,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd public get container() { const container = document.createElement('div'); container.id = `webview-${this.id}`; + container.style.visibility = 'hidden'; this._layoutService.getContainer(Parts.EDITOR_PART).appendChild(container); return container; } From 1628c72806cfbde837b75536d520315295a49e40 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 21:53:12 -0700 Subject: [PATCH 126/435] Run oss tool --- ThirdPartyNotices.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index aa56c32d53d..6fe67025875 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -27,7 +27,7 @@ This project incorporates components from the projects listed below. The origina 20. Ionic documentation version 1.2.4 (https://github.com/ionic-team/ionic-site) 21. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar) 22. jeff-hykin/cpp-textmate-grammar version 1.12.11 (https://github.com/jeff-hykin/cpp-textmate-grammar) -23. jeff-hykin/cpp-textmate-grammar version 1.13.2 (https://github.com/jeff-hykin/cpp-textmate-grammar) +23. jeff-hykin/cpp-textmate-grammar version 1.14.6 (https://github.com/jeff-hykin/cpp-textmate-grammar) 24. js-beautify version 1.6.8 (https://github.com/beautify-web/js-beautify) 25. Jxck/assert version 1.0.0 (https://github.com/Jxck/assert) 26. language-docker (https://github.com/moby/moby) @@ -65,7 +65,7 @@ This project incorporates components from the projects listed below. The origina 58. TypeScript-TmLanguage version 1.0.0 (https://github.com/Microsoft/TypeScript-TmLanguage) 59. Unicode version 12.0.0 (http://www.unicode.org/) 60. vscode-logfile-highlighter version 2.4.1 (https://github.com/emilast/vscode-logfile-highlighter) -61. vscode-octicons-font version 1.3.1 (https://github.com/Microsoft/vscode-octicons-font) +61. vscode-octicons-font version 1.3.2 (https://github.com/Microsoft/vscode-octicons-font) 62. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) 63. Web Background Synchronization (https://github.com/WICG/BackgroundSync) From a655c0836de8b8e06f4d56fa4e581b0ced53f56f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 2 Oct 2019 21:59:17 -0700 Subject: [PATCH 127/435] Bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 74a9dd79abe..a4f11bba946 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "516ad9e2679fb5f8a9d91bafcdc9d4d2f6005dfd", + "distro": "34784c4c1bcc5c753d86948b5dfc49ce916598b4", "author": { "name": "Microsoft Corporation" }, From 31a8a2c26e3c16b861c32cbfeecad1c46843ec48 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 3 Oct 2019 07:30:11 +0200 Subject: [PATCH 128/435] update distro --- package.json | 2 +- scripts/test-integration.bat | 1 - scripts/test-integration.sh | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index a4f11bba946..afb6b639628 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "34784c4c1bcc5c753d86948b5dfc49ce916598b4", + "distro": "967a5f6fb3ab3baa4f996b757db7312f81df41b5", "author": { "name": "Microsoft Corporation" }, diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 87773488204..d557a24edaa 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -20,7 +20,6 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" ( call yarn gulp compile-extension:css-language-features-server call yarn gulp compile-extension:html-language-features-server call yarn gulp compile-extension:json-language-features-server - call yarn gulp compile-extension:image-preview echo "Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build." ) diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index a695f774361..df6219221b7 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -29,7 +29,6 @@ else yarn gulp compile-extension:css-language-features-server yarn gulp compile-extension:html-language-features-server yarn gulp compile-extension:json-language-features-server - yarn gulp compile-extension:image-preview echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build." fi From bb9beb73b0930276e9d090b3ca0fb1e6491b58a0 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 3 Oct 2019 08:49:18 +0200 Subject: [PATCH 129/435] automatically assign debug issues to isidorn --- .github/classifier.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/classifier.yml b/.github/classifier.yml index 8acb0002347..c0c716d2526 100644 --- a/.github/classifier.yml +++ b/.github/classifier.yml @@ -15,7 +15,7 @@ css-less-scss: [], debug-console: [], debug: { - assignees: [ weinand ], + assignees: [ isidorn ], assignLabel: false }, diff-editor: : { From 925f3ab1a071b60ca5c674c547cf2b56b5c1f42b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 3 Oct 2019 08:50:55 +0200 Subject: [PATCH 130/435] fixes #81871 --- test/automation/src/scm.ts | 2 +- test/smoke/src/areas/git/git.test.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/automation/src/scm.ts b/test/automation/src/scm.ts index 2f56e31a87c..60a33abb93f 100644 --- a/test/automation/src/scm.ts +++ b/test/automation/src/scm.ts @@ -67,7 +67,7 @@ export class SCM extends Viewlet { async unstage(name: string): Promise { await this.code.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Unstage Changes')); - await this.waitForChange('app.js', 'Modified'); + await this.waitForChange(name, 'Modified'); } async commit(message: string): Promise { diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index a23a4f3080b..91948d04b1f 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -13,7 +13,6 @@ export function setup() { describe('Git', () => { before(async function () { const app = this.app as Application; - await app.workbench.settingsEditor.addUserSetting('scm.defaultViewMode', '"list"'); cp.execSync('git config user.name testuser', { cwd: app.workspacePathOrFolder }); cp.execSync('git config user.email monacotools@microsoft.com', { cwd: app.workspacePathOrFolder }); @@ -52,6 +51,7 @@ export function setup() { await app.workbench.scm.waitForChange('app.js', 'Modified'); await app.workbench.scm.stage('app.js'); + await app.workbench.scm.openChange('app.js'); await app.workbench.scm.unstage('app.js'); }); @@ -61,6 +61,7 @@ export function setup() { await app.workbench.scm.openSCMViewlet(); await app.workbench.scm.waitForChange('app.js', 'Modified'); + await app.workbench.scm.openChange('app.js'); await app.workbench.scm.stage('app.js'); await app.workbench.scm.commit('first commit'); From 3b5e571ef52228b287a01a04ed2effa084baf48f Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 3 Oct 2019 08:57:30 +0200 Subject: [PATCH 131/435] fixes #81868 --- src/vs/workbench/contrib/debug/browser/debug.contribution.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index a42bce188ed..74bccc63e53 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -261,6 +261,7 @@ configurationRegistry.registerConfiguration({ }, 'debug.onTaskErrors': { enum: ['debugAnyway', 'showErrors', 'prompt'], + enumDescriptions: [nls.localize('debugAnyway', "Ignore task errors and start debugging."), nls.localize('showErrors', "Show the Problems view and do not start debugging."), nls.localize('prompt', "Prompt user.")], description: nls.localize('debug.onTaskErrors', "Controls what to do when errors are encountered after running a preLaunchTask."), default: 'prompt' } From 229df29bc9bb6d7e2a731c1dbe879933fd8745cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 3 Oct 2019 09:03:13 +0200 Subject: [PATCH 132/435] Update README.md --- test/smoke/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/smoke/README.md b/test/smoke/README.md index dc905211950..5f86605f15a 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -43,7 +43,12 @@ yarn smoketest --build PATH_TO_NEW_RELEASE_PARENT_FOLDER --stable-build PATH_TO_ ### Develop -Start a watch task in `test/smoke`: +Start two watch tasks: + +```bash +cd test/automation +yarn watch +``` ```bash cd test/smoke From 84391a4685d66e88c38e682c5ad91c263fc204d0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 3 Oct 2019 10:20:19 +0200 Subject: [PATCH 133/435] remove product.welcomePage --- package.json | 2 +- .../platform/product/common/productService.ts | 2 - .../gettingStarted.contribution.ts | 2 - .../electron-browser/openWebsite.ts | 72 ------------------- .../environment/browser/environmentService.ts | 1 - .../environment/common/environmentService.ts | 1 - .../environment/node/environmentService.ts | 2 - 7 files changed, 1 insertion(+), 81 deletions(-) delete mode 100644 src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite.ts diff --git a/package.json b/package.json index afb6b639628..fc653251cbd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.39.0", - "distro": "967a5f6fb3ab3baa4f996b757db7312f81df41b5", + "distro": "b9bb6392c20ba05a247e41ea75b2825544fd8afd", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/platform/product/common/productService.ts b/src/vs/platform/product/common/productService.ts index f44dcee0455..5aa5c32d7ea 100644 --- a/src/vs/platform/product/common/productService.ts +++ b/src/vs/platform/product/common/productService.ts @@ -56,8 +56,6 @@ export interface IProductConfiguration { readonly productName: string; }; - readonly welcomePage?: string; - readonly enableTelemetry?: boolean; readonly aiConfig?: { readonly asimovKey: string; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts index e634543ae81..4a73fae2e2d 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts @@ -7,7 +7,5 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut'; -import { OpenWelcomePageInBrowser } from 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite'; -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(OpenWelcomePageInBrowser, LifecyclePhase.Restored); Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeTelemetryOptOut, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite.ts b/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite.ts deleted file mode 100644 index 7eb2bc0dc1c..00000000000 --- a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite.ts +++ /dev/null @@ -1,72 +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 { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import * as platform from 'vs/base/common/platform'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { URI } from 'vs/base/common/uri'; -import { IProductService } from 'vs/platform/product/common/productService'; - -export class OpenWelcomePageInBrowser implements IWorkbenchContribution { - - private static readonly hideWelcomeSettingskey = 'workbench.hide.welcome'; - - private welcomePageURL?: string; - private appName: string; - - constructor( - @IStorageService private readonly storageService: IStorageService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, - @ITelemetryService private readonly telemetryService: ITelemetryService, - @IOpenerService private readonly openerService: IOpenerService, - @IProductService productService: IProductService - ) { - this.appName = productService.nameLong; - this.welcomePageURL = productService.welcomePage; - - if ( - !productService.welcomePage || - environmentService.skipGettingStarted || - environmentService.isExtensionDevelopment - ) { - return; - } - - this.handleWelcome(); - } - - private getUrl(telemetryInfo: ITelemetryInfo): string { - return `${this.welcomePageURL}&&from=${this.appName}&&id=${telemetryInfo.machineId}`; - } - - private openExternal(url: string) { - // Don't open the welcome page as the root user on Linux, this is due to a bug with xdg-open - // which recommends against running itself as root. - if (platform.isLinux && platform.isRootUser()) { - return; - } - this.openerService.open(URI.parse(url)); - } - - private handleWelcome(): void { - //make sure the user is online, otherwise refer to the next run to show the welcome page - if (!navigator.onLine) { - return; - } - - let firstStartup = !this.storageService.get(OpenWelcomePageInBrowser.hideWelcomeSettingskey, StorageScope.GLOBAL); - - if (firstStartup && this.welcomePageURL) { - this.telemetryService.getTelemetryInfo().then(info => { - let url = this.getUrl(info); - this.openExternal(url); - this.storageService.store(OpenWelcomePageInBrowser.hideWelcomeSettingskey, true, StorageScope.GLOBAL); - }); - } - } -} diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index ee56e84cdc4..5f221e07ffc 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -170,7 +170,6 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment log?: string; logsPath: string; verbose: boolean; - skipGettingStarted: boolean; skipReleaseNotes: boolean; mainIPCHandle: string; sharedIPCHandle: string; diff --git a/src/vs/workbench/services/environment/common/environmentService.ts b/src/vs/workbench/services/environment/common/environmentService.ts index b19a45caf00..0f7a4d8e59a 100644 --- a/src/vs/workbench/services/environment/common/environmentService.ts +++ b/src/vs/workbench/services/environment/common/environmentService.ts @@ -28,7 +28,6 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService { readonly webviewResourceRoot: string; readonly webviewCspSource: string; - readonly skipGettingStarted: boolean | undefined; readonly skipReleaseNotes: boolean | undefined; } diff --git a/src/vs/workbench/services/environment/node/environmentService.ts b/src/vs/workbench/services/environment/node/environmentService.ts index 407fbe12c18..86732170c5f 100644 --- a/src/vs/workbench/services/environment/node/environmentService.ts +++ b/src/vs/workbench/services/environment/node/environmentService.ts @@ -36,8 +36,6 @@ export class WorkbenchEnvironmentService extends EnvironmentService implements I this.configuration.backupWorkspaceResource = this.configuration.backupPath ? toBackupWorkspaceResource(this.configuration.backupPath, this) : undefined; } - get skipGettingStarted(): boolean { return !!this.args['skip-getting-started']; } - get skipReleaseNotes(): boolean { return !!this.args['skip-release-notes']; } @memoize From 6bbe006248b41c9e025d14332ba417042fa4fccc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 3 Oct 2019 11:12:27 +0200 Subject: [PATCH 134/435] :lipstick: telemetry opt out --- .../browser/telemetryOptOut.contribution.ts} | 2 +- .../browser/telemetryOptOut.ts | 2 +- .../electron-browser/telemetryOptOut.contribution.ts} | 2 +- .../electron-browser/telemetryOptOut.ts | 2 +- src/vs/workbench/workbench.desktop.main.ts | 6 +++--- src/vs/workbench/workbench.web.main.ts | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) rename src/vs/workbench/contrib/welcome/{gettingStarted/browser/gettingStarted.contribution.ts => telemetryOptOut/browser/telemetryOptOut.contribution.ts} (94%) rename src/vs/workbench/contrib/welcome/{gettingStarted => telemetryOptOut}/browser/telemetryOptOut.ts (99%) rename src/vs/workbench/contrib/welcome/{gettingStarted/electron-browser/gettingStarted.contribution.ts => telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts} (93%) rename src/vs/workbench/contrib/welcome/{gettingStarted => telemetryOptOut}/electron-browser/telemetryOptOut.ts (97%) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.contribution.ts similarity index 94% rename from src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.contribution.ts index ab15e8a07ee..d0440e20402 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.contribution.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Registry } from 'vs/platform/registry/common/platform'; -import { BrowserTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut'; +import { BrowserTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts similarity index 99% rename from src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts index b60f680e467..4a84a56125d 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts @@ -100,7 +100,7 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution return this.galleryService.getCoreTranslation(extensionToFetchTranslationsFrom, locale!) .then(translation => { - const translationsFromPack: any = translation && translation.contents ? translation.contents['vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut'] : {}; + const translationsFromPack: any = translation && translation.contents ? translation.contents['vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut'] : {}; if (!!translationsFromPack[promptMessageKey] && !!translationsFromPack[yesLabelKey] && !!translationsFromPack[noLabelKey]) { promptMessage = translationsFromPack[promptMessageKey].replace('{0}', this.privacyUrl) + ' (Please help Microsoft improve Visual Studio Code by allowing the collection of usage data.)'; yesLabel = translationsFromPack[yesLabelKey] + ' (Yes)'; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts similarity index 93% rename from src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts index 4a73fae2e2d..44b1e266005 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts @@ -6,6 +6,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut'; +import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut'; Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeTelemetryOptOut, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts similarity index 97% rename from src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts index ae045c341a3..d561cf83320 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts @@ -12,7 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IProductService } from 'vs/platform/product/common/productService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { AbstractTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut'; +import { AbstractTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut'; import { IElectronService } from 'vs/platform/electron/node/electron'; export class NativeTelemetryOptOut extends AbstractTelemetryOptOut { diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index ee57288fc95..18980940dfb 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -62,6 +62,7 @@ import 'vs/workbench/services/update/electron-browser/updateService'; import 'vs/workbench/services/issue/electron-browser/issueService'; import 'vs/workbench/services/menubar/electron-browser/menubarService'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService'; @@ -129,11 +130,10 @@ import 'vs/workbench/contrib/tasks/electron-browser/taskService'; // User Data Sync import 'vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution'; -// Welcome -import 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted.contribution'; +// Telemetry Opt Out +import 'vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution'; // Configuration Exporter import 'vs/workbench/contrib/configExporter/node/configurationExportHelper.contribution'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; //#endregion diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index f5fe40a4cae..fa9c9dd7a90 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -105,7 +105,7 @@ import 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; // Tasks import 'vs/workbench/contrib/tasks/browser/taskService'; -// Welcome -import 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution'; +// Telemetry Opt Out +import 'vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.contribution'; //#endregion From 6a90438f026b3de6ca119b8858411916cd006eff Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 3 Oct 2019 11:44:30 +0200 Subject: [PATCH 135/435] WSL window opening with windows path. Fixes https://github.com/microsoft/vscode-remote-release/issues/1537 --- src/vs/code/node/paths.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/code/node/paths.ts b/src/vs/code/node/paths.ts index ce4e1b0227a..fb191e7fe08 100644 --- a/src/vs/code/node/paths.ts +++ b/src/vs/code/node/paths.ts @@ -19,12 +19,14 @@ export function validatePaths(args: ParsedArgs): ParsedArgs { args._ = []; } - // Normalize paths and watch out for goto line mode - const paths = doValidatePaths(args._, args.goto); + if (!args['remote']) { + // Normalize paths and watch out for goto line mode + const paths = doValidatePaths(args._, args.goto); + args._ = paths; + } // Update environment - args._ = paths; - args.diff = args.diff && paths.length === 2; + args.diff = args.diff && args._.length === 2; return args; } @@ -135,4 +137,4 @@ function toPath(p: IPathWithLineAndColumn): string { } return segments.join(':'); -} \ No newline at end of file +} From 6ff7bf27c9dc447cd95693debdc5b90910e804b5 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Oct 2019 14:52:59 +0200 Subject: [PATCH 136/435] Fix settings conflict when opening files locally Fixes https://github.com/microsoft/vscode-remote-release/issues/980 --- .../services/dialogs/electron-browser/fileDialogService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts index 44790f68ce5..e317751fd39 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts @@ -46,8 +46,8 @@ export class FileDialogService extends AbstractFileDialogService implements IFil private shouldUseSimplified(schema: string): { useSimplified: boolean, isSetting: boolean } { const setting = (this.configurationService.getValue('files.simpleDialog.enable') === true); - - return { useSimplified: (schema !== Schemas.file) || setting, isSetting: (schema === Schemas.file) && setting }; + const newWindowSetting = (this.configurationService.getValue('window.openFilesInNewWindow') === 'on'); + return { useSimplified: (schema !== Schemas.file) || setting, isSetting: newWindowSetting }; } async pickFileFolderAndOpen(options: IPickAndOpenOptions): Promise { From 53d6601137343ac261c7e76a15af88dee2e43049 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 3 Oct 2019 16:51:03 +0200 Subject: [PATCH 137/435] strict init --- src/vs/workbench/api/common/extHostSCM.ts | 8 ++++---- src/vs/workbench/api/worker/extHostExtensionService.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 80c0c007f65..769d90c8d17 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -174,9 +174,9 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { this._placeholder = placeholder; } - private _validateInput: IValidateInput; + private _validateInput: IValidateInput | undefined; - get validateInput(): IValidateInput { + get validateInput(): IValidateInput | undefined { if (!this._extension.enableProposedApi) { throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`); } @@ -184,7 +184,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { return this._validateInput; } - set validateInput(fn: IValidateInput) { + set validateInput(fn: IValidateInput | undefined) { if (!this._extension.enableProposedApi) { throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`); } @@ -667,7 +667,7 @@ export class ExtHostSCM implements ExtHostSCMShape { return Promise.resolve(undefined); } - return asPromise(() => sourceControl.inputBox.validateInput(value, cursorPosition)).then(result => { + return asPromise(() => sourceControl.inputBox.validateInput!(value, cursorPosition)).then(result => { if (!result) { return Promise.resolve(undefined); } diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index afd82468c06..4781f226762 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -32,7 +32,7 @@ class WorkerRequireInterceptor extends RequireInterceptor { export class ExtHostExtensionService extends AbstractExtHostExtensionService { - private _fakeModules: WorkerRequireInterceptor; + private _fakeModules?: WorkerRequireInterceptor; protected async _beforeAlmostReadyToRunExtensions(): Promise { // initialize API and register actors @@ -57,7 +57,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { const _exports = {}; const _module = { exports: _exports }; const _require = (request: string) => { - const result = this._fakeModules.getModule(request, module); + const result = this._fakeModules!.getModule(request, module); if (result === undefined) { throw new Error(`Cannot load module '${request}'`); } From e0729a52ab6f4159f1dd70a12f1d15e2b0200156 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Oct 2019 17:09:16 +0200 Subject: [PATCH 138/435] Fix to many messages whn cancelling resolution of contributed variables Fixes https://github.com/microsoft/vscode/issues/81767 --- .../browser/configurationResolverService.ts | 18 ++++- .../common/variableResolver.ts | 81 +++---------------- 2 files changed, 25 insertions(+), 74 deletions(-) diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index 680042ebb70..7888b56c501 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -91,21 +91,21 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR config = await this.resolveAny(folder, config); // resolve input variables in the order in which they are encountered - return this.resolveWithInteraction(folder, config, section, variables, false).then(mapping => { + return this.resolveWithInteraction(folder, config, section, variables).then(mapping => { // finally substitute evaluated command variables (if there are any) if (!mapping) { return null; } else if (mapping.size > 0) { - return this.resolveAny(folder, config, fromMap(mapping), false); + return this.resolveAny(folder, config, fromMap(mapping)); } else { return config; } }); } - public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary, resolveContributed: boolean = true): Promise | undefined> { + public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary): Promise | undefined> { // resolve any non-interactive variables and any contributed variables - const resolved = await this.resolveAnyMap(folder, config, resolveContributed); + const resolved = await this.resolveAnyMap(folder, config); config = resolved.newConfig; const allVariableMapping: Map = resolved.resolvedVariables; @@ -180,6 +180,11 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR throw new Error(nls.localize('commandVariable.noStringType', "Cannot substitute command variable '{0}' because command did not return a result of type string.", commandId)); } break; + default: + // Try to resolve it as a contributed variable + if (this._contributedVariables.has(variable)) { + result = await this._contributedVariables.get(variable)!(); + } } if (typeof result === 'string') { @@ -208,6 +213,11 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR } } } + this._contributedVariables.forEach((value, contributed: string) => { + if ((variables.indexOf(contributed) < 0) && (object.indexOf('${' + contributed + '}') >= 0)) { + variables.push(contributed); + } + }); } else if (Types.isArray(object)) { object.forEach(value => { this.findVariables(value, variables); diff --git a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts index 1e75e82e345..32242293645 100644 --- a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts @@ -32,7 +32,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe _serviceBrand: undefined; - private _contributedVariables: Map Promise> = new Map(); + protected _contributedVariables: Map Promise> = new Map(); constructor( private _context: IVariableResolveContext, @@ -53,7 +53,8 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return this.recursiveResolve(root ? root.uri : undefined, value); } - private async resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { + public resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): any { + const result = objects.deepClone(config) as any; // hoist platform specific attributes to top level @@ -71,16 +72,16 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe delete result.linux; // substitute all variables recursively in string values - return this.recursiveResolvePromise(workspaceFolder ? workspaceFolder.uri : undefined, result, resolveContributed, commandValueMapping, resolvedVariables); + return this.recursiveResolve(workspaceFolder ? workspaceFolder.uri : undefined, result, commandValueMapping, resolvedVariables); } - public resolveAny(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolveContributed: boolean = true): Promise { - return this.resolveAnyBase(workspaceFolder, config, resolveContributed, commandValueMapping); + public resolveAny(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): any { + return this.resolveAnyBase(workspaceFolder, config, commandValueMapping); } - protected async resolveAnyMap(workspaceFolder: IWorkspaceFolder | undefined, config: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary): Promise<{ newConfig: any, resolvedVariables: Map }> { + public resolveAnyMap(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): { newConfig: any, resolvedVariables: Map } { const resolvedVariables = new Map(); - const newConfig = await this.resolveAnyBase(workspaceFolder, config, resolveContributed, commandValueMapping, resolvedVariables); + const newConfig = this.resolveAnyBase(workspaceFolder, config, commandValueMapping, resolvedVariables); return { newConfig, resolvedVariables }; } @@ -116,23 +117,6 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return value; } - private async recursiveResolvePromise(folderUri: uri | undefined, value: any, resolveContributed: boolean, commandValueMapping?: IStringDictionary, resolvedVariables?: Map): Promise { - if (types.isString(value)) { - return this.resolveStringPromise(folderUri, value, commandValueMapping, resolveContributed, resolvedVariables); - } else if (types.isArray(value)) { - return Promise.all(value.map(s => this.recursiveResolvePromise(folderUri, s, resolveContributed, commandValueMapping, resolvedVariables))); - } else if (types.isObject(value)) { - let result: IStringDictionary | string[]> = Object.create(null); - const keys = Object.keys(value); - for (let key of keys) { - const replaced = await this.resolveStringPromise(folderUri, key, commandValueMapping, resolveContributed, resolvedVariables); - result[replaced] = await this.recursiveResolvePromise(folderUri, value[key], resolveContributed, commandValueMapping, resolvedVariables); - } - return result; - } - return value; - } - private resolveString(folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary | undefined, resolvedVariables?: Map): string { // loop through all variables occurrences in 'value' @@ -150,39 +134,6 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return replaced; } - private async resolveStringPromise(folderUri: uri | undefined, value: string, commandValueMapping: IStringDictionary | undefined, resolveContributed: boolean, resolvedVariables?: Map): Promise { - // loop through all variables occurrences in 'value' - const matches = value.match(AbstractVariableResolverService.VARIABLE_REGEXP); - const replaces: Map = new Map(); - if (!matches) { - return value; - } - if (resolveContributed) { - for (const match of matches) { - const evaluate = await this.evaluateSingleContributedVariable(match, match.match(AbstractVariableResolverService.VARIABLE_REGEXP_SINGLE)![1]); - if (evaluate !== match) { - replaces.set(match, evaluate); - } - } - } - - const replaced = value.replace(AbstractVariableResolverService.VARIABLE_REGEXP, (match: string, variable: string) => { - - let resolvedValue = this.evaluateSingleVariable(match, variable, folderUri, commandValueMapping); - if ((resolvedValue === match) && (replaces.has(match))) { - resolvedValue = replaces.get(match)!; - } - - if (resolvedVariables) { - resolvedVariables.set(variable, resolvedValue); - } - - return resolvedValue; - }); - - return replaced; - } - private evaluateSingleVariable(match: string, variable: string, folderUri: uri | undefined, commandValueMapping: IStringDictionary | undefined): string { // try to separate variable arguments from variable name @@ -325,25 +276,15 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return match; default: - return match; + return this.resolveFromMap(match, variable, commandValueMapping, undefined); } } } } - private async evaluateSingleContributedVariable(match: string, variable: string): Promise { - if (this._contributedVariables.has(variable)) { - const contributedValue: string | undefined = await this._contributedVariables.get(variable)!(); - if (contributedValue !== undefined) { - return contributedValue; - } - } - return match; - } - - private resolveFromMap(match: string, argument: string | undefined, commandValueMapping: IStringDictionary | undefined, prefix: string): string { + private resolveFromMap(match: string, argument: string | undefined, commandValueMapping: IStringDictionary | undefined, prefix: string | undefined): string { if (argument && commandValueMapping) { - const v = commandValueMapping[prefix + ':' + argument]; + const v = (prefix === undefined) ? commandValueMapping[argument] : commandValueMapping[prefix + ':' + argument]; if (typeof v === 'string') { return v; } From 58c72545cd625c556988ad7937243681cef367cf Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 3 Oct 2019 17:15:50 +0200 Subject: [PATCH 139/435] explorer: add decoration provider to disposables microsoft/vscode-remote-release#1598 --- src/vs/workbench/contrib/files/browser/views/explorerView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index fda43517833..359ad9abfa5 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -101,7 +101,7 @@ export class ExplorerView extends ViewletPanel { this.resourceMoveableToTrash = ExplorerResourceMoveableToTrash.bindTo(contextKeyService); const decorationProvider = new ExplorerDecorationsProvider(this.explorerService, contextService); - decorationService.registerDecorationsProvider(decorationProvider); + this._register(decorationService.registerDecorationsProvider(decorationProvider)); this._register(decorationProvider); this._register(this.resourceContext); } From 88927741745df7e84178fcaf4660b1c6bc8a0818 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 3 Oct 2019 17:22:18 +0200 Subject: [PATCH 140/435] Fix configuration resolver test --- .../browser/configurationResolverService.ts | 2 +- .../configurationResolver/common/configurationResolver.ts | 2 +- .../test/electron-browser/configurationResolverService.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index 7888b56c501..a4eedf25bfb 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -88,7 +88,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR public async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary): Promise { // resolve any non-interactive variables and any contributed variables - config = await this.resolveAny(folder, config); + config = this.resolveAny(folder, config); // resolve input variables in the order in which they are encountered return this.resolveWithInteraction(folder, config, section, variables).then(mapping => { diff --git a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts index 493824af804..df0da9e454f 100644 --- a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts @@ -20,7 +20,7 @@ export interface IConfigurationResolverService { * Recursively resolves all variables in the given config and returns a copy of it with substituted values. * Command variables are only substituted if a "commandValueMapping" dictionary is given and if it contains an entry for the command. */ - resolveAny(folder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary, resolveContributed?: boolean): Promise; + resolveAny(folder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary): any; /** * Recursively resolves all variables (including commands and user input) in the given config and returns a copy of it with substituted values. diff --git a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts index fe86b65a202..04c50e16b17 100644 --- a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts @@ -494,7 +494,7 @@ suite('Configuration Resolver Service', () => { 'name': '${' + variable + '}', }; configurationResolverService!.contributeVariable(variable, async () => { return buildTask; }); - return configurationResolverService!.resolveAny(workspace, configuration).then(result => { + return configurationResolverService!.resolveWithInteractionReplace(workspace, configuration).then(result => { assert.deepEqual(result, { 'name': `${buildTask}` }); From 4f6e116539264248707f37261243fdf41fa2b058 Mon Sep 17 00:00:00 2001 From: Nikolay Kondratyev Date: Wed, 2 Oct 2019 16:24:47 +0300 Subject: [PATCH 141/435] Use yarn compile for start scripts --- scripts/code-cli.bat | 2 +- scripts/code-cli.sh | 2 +- scripts/code.bat | 2 +- scripts/code.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/code-cli.bat b/scripts/code-cli.bat index 6fbf5edd626..56c37567201 100644 --- a/scripts/code-cli.bat +++ b/scripts/code-cli.bat @@ -24,7 +24,7 @@ if "%1"=="--builtin" goto builtin node build\lib\builtInExtensions.js :: Build -if not exist out node .\node_modules\gulp\bin\gulp.js compile +if not exist out yarn compile :: Configuration set ELECTRON_RUN_AS_NODE=1 diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh index a7d61d5a897..e42beeed5bf 100755 --- a/scripts/code-cli.sh +++ b/scripts/code-cli.sh @@ -35,7 +35,7 @@ function code() { node build/lib/builtInExtensions.js # Build - test -d out || ./node_modules/.bin/gulp compile + test -d out || yarn compile ELECTRON_RUN_AS_NODE=1 \ NODE_ENV=development \ diff --git a/scripts/code.bat b/scripts/code.bat index f4689608e4a..0eb0eb0b342 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -24,7 +24,7 @@ if "%1"=="--builtin" goto builtin node build\lib\builtInExtensions.js :: Build -if not exist out node .\node_modules\gulp\bin\gulp.js compile +if not exist out yarn compile :: Configuration set NODE_ENV=development diff --git a/scripts/code.sh b/scripts/code.sh index e82babd818a..0440e49e71a 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -39,7 +39,7 @@ function code() { node build/lib/builtInExtensions.js # Build - test -d out || ./node_modules/.bin/gulp compile + test -d out || yarn compile # Configuration export NODE_ENV=development From 2b9bb7c2e0f51a6b9a07faa6352abf81b28cf4d7 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 3 Oct 2019 09:33:34 -0700 Subject: [PATCH 142/435] Update css language service --- extensions/css-language-features/server/package.json | 2 +- extensions/css-language-features/server/yarn.lock | 8 ++++---- extensions/html-language-features/server/package.json | 2 +- extensions/html-language-features/server/yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 3d840a8346e..a263ed94c2e 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,7 +9,7 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.10", + "vscode-css-languageservice": "^4.0.3-next.11", "vscode-languageserver": "^6.0.0-next.1" }, "devDependencies": { diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 66d2c02ad80..6d38104e2e5 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -781,10 +781,10 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.10: - version "4.0.3-next.10" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.10.tgz#e282e49303cdda267c2e72dc00d8c5fa1db4ec3c" - integrity sha512-dJFx71TzA5wfl46jrtbLR/Hm42CsuRJbeVlgEMcf2DcDtq7caw5iWGK7Ch4clALmjIyWPPXFWOyEo9kzZl26pw== +vscode-css-languageservice@^4.0.3-next.11: + version "4.0.3-next.11" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.11.tgz#b353ae30551c052e7133f6640d5f4d4755c27fb0" + integrity sha512-6rdruqzWkAbGkTw56WTMS7SmhOYIZ4Dnrs3Wc64cn/saF1f+ib76EUvISiYLZnc+S9FsZu2lnlzPeeJ3LItm2A== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index a51fb648fd7..58f9762e846 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,7 +9,7 @@ }, "main": "./out/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.3-next.10", + "vscode-css-languageservice": "^4.0.3-next.11", "vscode-html-languageservice": "^3.0.4-next.5", "vscode-languageserver": "^6.0.0-next.1", "vscode-languageserver-types": "3.15.0-next.5", diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index db7cefb3430..feed2d264a1 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -611,10 +611,10 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.3-next.10: - version "4.0.3-next.10" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.10.tgz#e282e49303cdda267c2e72dc00d8c5fa1db4ec3c" - integrity sha512-dJFx71TzA5wfl46jrtbLR/Hm42CsuRJbeVlgEMcf2DcDtq7caw5iWGK7Ch4clALmjIyWPPXFWOyEo9kzZl26pw== +vscode-css-languageservice@^4.0.3-next.11: + version "4.0.3-next.11" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.11.tgz#b353ae30551c052e7133f6640d5f4d4755c27fb0" + integrity sha512-6rdruqzWkAbGkTw56WTMS7SmhOYIZ4Dnrs3Wc64cn/saF1f+ib76EUvISiYLZnc+S9FsZu2lnlzPeeJ3LItm2A== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" From 355676f84f02d6400856224bb59f8fd79238be07 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 3 Oct 2019 09:50:55 -0700 Subject: [PATCH 143/435] Fix #79840 --- src/vs/workbench/api/common/extHostTypes.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 79cd4779316..981050bbef7 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1227,7 +1227,9 @@ export class MarkdownString { appendText(value: string): MarkdownString { // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash - this.value += value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'); + this.value += value + .replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') + .replace('\n', '\n\n'); return this; } From 096eb643d1af85e237aabbdce5b0b8a1c9f578f4 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Thu, 3 Oct 2019 13:27:40 -0500 Subject: [PATCH 144/435] Fixes #81876 (#81885) --- extensions/image-preview/media/main.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/extensions/image-preview/media/main.js b/extensions/image-preview/media/main.js index cd39eb9a53f..34c9708df99 100644 --- a/extensions/image-preview/media/main.js +++ b/extensions/image-preview/media/main.js @@ -88,9 +88,6 @@ image.style.width = 'auto'; vscode.setState(undefined); } else { - const oldWidth = image.width; - const oldHeight = image.height; - scale = clamp(newScale, MIN_SCALE, MAX_SCALE); if (scale >= PIXELATION_THRESHOLD) { image.classList.add('pixelated'); @@ -98,25 +95,19 @@ image.classList.remove('pixelated'); } - const { scrollTop, scrollLeft } = image.parentElement; - const dx = (scrollLeft + image.parentElement.clientWidth / 2) / image.parentElement.scrollWidth; - const dy = (scrollTop + image.parentElement.clientHeight / 2) / image.parentElement.scrollHeight; + const dx = (window.scrollX + container.clientWidth / 2) / container.scrollWidth; + const dy = (window.scrollY + container.clientHeight / 2) / container.scrollHeight; image.classList.remove('scale-to-fit'); image.style.minWidth = `${(image.naturalWidth * scale)}px`; image.style.width = `${(image.naturalWidth * scale)}px`; - const newWidth = image.width; - const scaleFactor = (newWidth - oldWidth) / oldWidth; + const newScrollX = container.scrollWidth * dx - container.clientWidth / 2; + const newScrollY = container.scrollHeight * dy - container.clientHeight / 2; - const newScrollLeft = ((oldWidth * scaleFactor * dx) + scrollLeft); - const newScrollTop = ((oldHeight * scaleFactor * dy) + scrollTop); - // scrollbar.setScrollPosition({ - // scrollLeft: newScrollLeft, - // scrollTop: newScrollTop, - // }); + window.scrollTo(newScrollX, newScrollY); - vscode.setState({ scale: scale, offsetX: newScrollLeft, offsetY: newScrollTop }); + vscode.setState({ scale: scale, offsetX: newScrollX, offsetY: newScrollY }); } vscode.postMessage({ From 9a8f8671294f1a743eb20056d0170736994e7963 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Oct 2019 11:30:45 -0700 Subject: [PATCH 145/435] Use `name` for custom editor title for data uri resources Fixes #81791 --- .../contrib/customEditor/browser/customEditorInput.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 7af6673ed7b..bfaf0a98bcf 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -86,11 +86,17 @@ export class CustomFileEditorInput extends WebviewInput { @memoize private get mediumTitle(): string { + if (this.getResource().scheme === Schemas.data) { + return this.getName(); + } return this.labelService.getUriLabel(this.getResource(), { relative: true }); } @memoize private get longTitle(): string { + if (this.getResource().scheme === Schemas.data) { + return this.getName(); + } return this.labelService.getUriLabel(this.getResource()); } From 17db07b22c3bd270b418ee26663fda9127d3dba9 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 11:36:11 -0700 Subject: [PATCH 146/435] Adopt icon font in problems panel and error peek view --- .../contrib/gotoError/gotoErrorWidget.ts | 2 +- .../severityIcon/common/severityIcon.ts | 89 ++++++++----------- src/vs/platform/theme/common/colorRegistry.ts | 3 + src/vs/workbench/common/theme.ts | 20 ++--- .../markers/browser/markersTreeViewer.ts | 2 +- .../contrib/markers/browser/media/markers.css | 10 ++- 6 files changed, 60 insertions(+), 66 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts index 3c94a3b561a..c6a10084db3 100644 --- a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -283,7 +283,7 @@ export class MarkerNavigationWidget extends PeekViewWidget { : nls.localize('change', "{0} of {1} problem", markerIdx, markerCount); this.setTitle(basename(model.uri), detail); } - this._icon.className = SeverityIcon.className(MarkerSeverity.toSeverity(this._severity)); + this._icon.className = 'codicon ' + SeverityIcon.className(MarkerSeverity.toSeverity(this._severity)); this.editor.revealPositionInCenter(position, ScrollType.Smooth); } diff --git a/src/vs/platform/severityIcon/common/severityIcon.ts b/src/vs/platform/severityIcon/common/severityIcon.ts index 52eae1a08cc..98019496e51 100644 --- a/src/vs/platform/severityIcon/common/severityIcon.ts +++ b/src/vs/platform/severityIcon/common/severityIcon.ts @@ -4,70 +4,55 @@ *--------------------------------------------------------------------------------------------*/ import Severity from 'vs/base/common/severity'; -import { registerThemingParticipant, ITheme, LIGHT } from 'vs/platform/theme/common/themeService'; -import { Color } from 'vs/base/common/color'; - -const errorStart = encodeURIComponent(``); -const errorDarkStart = encodeURIComponent(``); - -const warningStart = encodeURIComponent(``); -const warningDarkStart = encodeURIComponent(``); - -const infoStart = encodeURIComponent(``); -const infoDarkStart = encodeURIComponent(``); +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { problemsErrorIconForeground, problemsInfoIconForeground, problemsWarningIconForeground } from 'vs/platform/theme/common/colorRegistry'; export namespace SeverityIcon { - export function getSVGData(severity: Severity, theme: ITheme): string { - switch (severity) { - case Severity.Ignore: - const ignoreColor = theme.type === LIGHT ? Color.fromHex('#75BEFF') : Color.fromHex('#007ACC'); - return theme.type === LIGHT ? infoStart + encodeURIComponent(ignoreColor.toString()) + infoEnd - : infoDarkStart + encodeURIComponent(ignoreColor.toString()) + infoDarkEnd; - case Severity.Info: - const infoColor = theme.type === LIGHT ? Color.fromHex('#007ACC') : Color.fromHex('#75BEFF'); - return theme.type === LIGHT ? infoStart + encodeURIComponent(infoColor.toString()) + infoEnd - : infoDarkStart + encodeURIComponent(infoColor.toString()) + infoDarkEnd; - case Severity.Warning: - const warningColor = theme.type === LIGHT ? Color.fromHex('#DDB100') : Color.fromHex('#fc0'); - return theme.type === LIGHT ? warningStart + encodeURIComponent(warningColor.toString()) + warningEnd - : warningDarkStart + encodeURIComponent(warningColor.toString()) + warningDarkEnd; - case Severity.Error: - const errorColor = theme.type === LIGHT ? Color.fromHex('#A1260D') : Color.fromHex('#F48771'); - return theme.type === LIGHT ? errorStart + encodeURIComponent(errorColor.toString()) + errorEnd - : errorDarkStart + encodeURIComponent(errorColor.toString()) + errorDarkEnd; - } - return ''; - } - export function className(severity: Severity): string { switch (severity) { case Severity.Ignore: - return 'severity-icon severity-ignore'; + return 'severity-ignore codicon-info'; case Severity.Info: - return 'severity-icon severity-info'; + return 'codicon-info'; case Severity.Warning: - return 'severity-icon severity-warning'; + return 'codicon-warning'; case Severity.Error: - return 'severity-icon severity-error'; + return 'codicon-error'; } return ''; } } -function getCSSRule(severity: Severity, theme: ITheme): string { - return `.${SeverityIcon.className(severity).split(' ').join('.')} { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(severity, theme)}") center center no-repeat; height: 16px; width: 16px; }`; -} +registerThemingParticipant((thme, collector) => { -registerThemingParticipant((theme, collector) => { - collector.addRule(getCSSRule(Severity.Error, theme)); - collector.addRule(getCSSRule(Severity.Warning, theme)); - collector.addRule(getCSSRule(Severity.Info, theme)); - collector.addRule(getCSSRule(Severity.Ignore, theme)); -}); \ No newline at end of file + const errorIconForeground = theme.getColor(problemsErrorIconForeground); + if (errorIconForeground) { + collector.addRule(` + .monaco-workbench .zone-widget .codicon-error, + .monaco-workbench .markers-panel .marker-icon.codicon-error { + color: ${errorIconForeground}; + } + `); + } + + const warningIconForeground = theme.getColor(problemsWarningIconForeground); + if (errorIconForeground) { + collector.addRule(` + .monaco-workbench .zone-widget .codicon-warning, + .monaco-workbench .markers-panel .marker-icon.codicon-warning { + color: ${warningIconForeground}; + } + `); + } + + const infoIconForeground = theme.getColor(problemsInfoIconForeground); + if (errorIconForeground) { + collector.addRule(` + .monaco-workbench .zone-widget .codicon-info, + .monaco-workbench .markers-panel .marker-icon.codicon-info { + color: ${infoIconForeground}; + } + `); + } +}); diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index fe1403f4ede..6d8af22abb9 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -406,6 +406,9 @@ export const overviewRulerSelectionHighlightForeground = registerColor('editorOv export const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hc: '#AB5A00' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true); export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#ffffff' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the editor selection.'), true); +export const problemsErrorIconForeground = registerColor('problemsErrorIcon.foreground', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('problemsErrorIconForeground', "The color used for the problems error icon.")); +export const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('problemsWarningIconForeground', "The color used for the problems warning icon.")); +export const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('problemsInfoIconForeground', "The color used for the problems info icon.")); // ----- color functions diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 7d81c6c5e72..fc41153b077 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground } from 'vs/platform/theme/common/colorRegistry'; +import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground, editorErrorForeground, editorWarningForeground, editorInfoForeground } from 'vs/platform/theme/common/colorRegistry'; import { Disposable } from 'vs/base/common/lifecycle'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; @@ -560,21 +560,21 @@ export const NOTIFICATIONS_BORDER = registerColor('notifications.border', { }, nls.localize('notificationsBorder', "Notifications border color separating from other notifications in the notifications center. Notifications slide in from the bottom right of the window.")); export const NOTIFICATIONS_ERROR_ICON_FOREGROUND = registerColor('notificationsErrorIcon.foreground', { - dark: '#F48771', - light: '#A1260D', - hc: '#F48771' + dark: editorErrorForeground, + light: editorErrorForeground, + hc: editorErrorForeground }, nls.localize('notificationsErrorIconForeground', "The color used for the notification error icon.")); export const NOTIFICATIONS_WARNING_ICON_FOREGROUND = registerColor('notificationsWarningIcon.foreground', { - dark: '#FFCC00', - light: '#DDB100', - hc: '#FFCC00' + dark: editorWarningForeground, + light: editorWarningForeground, + hc: editorWarningForeground }, nls.localize('notificationsWarningIconForeground', "The color used for the notification warning icon.")); export const NOTIFICATIONS_INFO_ICON_FOREGROUND = registerColor('notificationsInfoIcon.foreground', { - dark: '#75BEFF', - light: '#007ACC', - hc: '#75BEFF' + dark: editorInfoForeground, + light: editorInfoForeground, + hc: editorInfoForeground }, nls.localize('notificationsInfoIconForeground', "The color used for the notification info icon.")); /** diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index 90158388b30..697bfbcff29 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -267,7 +267,7 @@ class MarkerWidget extends Disposable { this.disposables.clear(); dom.clearNode(this.messageAndDetailsContainer); - this.icon.className = `marker-icon ${SeverityIcon.className(MarkerSeverity.toSeverity(element.marker.severity))}`; + this.icon.className = `marker-icon codicon ${SeverityIcon.className(MarkerSeverity.toSeverity(element.marker.severity))}`; this.renderQuickfixActionbar(element); this.renderMultilineActionbar(element); diff --git a/src/vs/workbench/contrib/markers/browser/media/markers.css b/src/vs/workbench/contrib/markers/browser/media/markers.css index cdec9f47999..cf54727d396 100644 --- a/src/vs/workbench/contrib/markers/browser/media/markers.css +++ b/src/vs/workbench/contrib/markers/browser/media/markers.css @@ -132,9 +132,15 @@ margin-left: 6px; } -.markers-panel .monaco-tl-contents .marker-icon, -.markers-panel .monaco-tl-contents .actions .action-item { +.markers-panel .monaco-tl-contents .marker-icon { margin-right: 6px; + display: flex; + align-items: center; + justify-content: center; +} + +.markers-panel .monaco-tl-contents .actions .action-item { + margin-right: 2px; } .markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-source, From ef381e5573ceacd85a91f1a0e31d440a8b711e80 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 11:40:27 -0700 Subject: [PATCH 147/435] Fix #81916 --- src/vs/editor/contrib/gotoError/gotoError.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index c16b9be9a6e..f2ebe3575c3 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -248,8 +248,8 @@ export class MarkerController implements editorCommon.IEditorContribution { const prevMarkerKeybinding = this._keybindingService.lookupKeybinding(PrevMarkerAction.ID); const nextMarkerKeybinding = this._keybindingService.lookupKeybinding(NextMarkerAction.ID); const actions = [ - new Action(PrevMarkerAction.ID, PrevMarkerAction.LABEL + (prevMarkerKeybinding ? ` (${prevMarkerKeybinding.getLabel()})` : ''), 'show-previous-problem chevron-up', this._model.canNavigate(), async () => { if (this._model) { this._model.move(false, true); } }), - new Action(NextMarkerAction.ID, NextMarkerAction.LABEL + (nextMarkerKeybinding ? ` (${nextMarkerKeybinding.getLabel()})` : ''), 'show-next-problem chevron-down', this._model.canNavigate(), async () => { if (this._model) { this._model.move(true, true); } }) + new Action(PrevMarkerAction.ID, PrevMarkerAction.LABEL + (prevMarkerKeybinding ? ` (${prevMarkerKeybinding.getLabel()})` : ''), 'show-previous-problem codicon-chevron-up', this._model.canNavigate(), async () => { if (this._model) { this._model.move(false, true); } }), + new Action(NextMarkerAction.ID, NextMarkerAction.LABEL + (nextMarkerKeybinding ? ` (${nextMarkerKeybinding.getLabel()})` : ''), 'show-next-problem codicon-chevron-down', this._model.canNavigate(), async () => { if (this._model) { this._model.move(true, true); } }) ]; this._widget = new MarkerNavigationWidget(this._editor, actions, this._themeService); this._widgetVisible.set(true); @@ -522,4 +522,4 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, { title: nls.localize({ key: 'miGotoPreviousProblem', comment: ['&& denotes a mnemonic'] }, "Previous &&Problem") }, order: 2 -}); \ No newline at end of file +}); From b88efcac1d2c19253247cc9c84d77641ab1c6b77 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 3 Oct 2019 11:54:25 -0700 Subject: [PATCH 148/435] Bump node2 --- build/builtInExtensions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json index 76a1e1e51fc..bedc2d3ed52 100644 --- a/build/builtInExtensions.json +++ b/build/builtInExtensions.json @@ -16,7 +16,7 @@ }, { "name": "ms-vscode.node-debug2", - "version": "1.39.0", + "version": "1.39.1", "repo": "https://github.com/Microsoft/vscode-node-debug2", "metadata": { "id": "36d19e17-7569-4841-a001-947eb18602b2", From 8266e1c67b0dff28fc8fa24ecde325e8a7e91cd6 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 3 Oct 2019 11:44:56 -0700 Subject: [PATCH 149/435] Fix #81843 --- .../trustedDomainsFileSystemProvider.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/url/common/trustedDomainsFileSystemProvider.ts b/src/vs/workbench/contrib/url/common/trustedDomainsFileSystemProvider.ts index ba66812aab7..d007281fc3b 100644 --- a/src/vs/workbench/contrib/url/common/trustedDomainsFileSystemProvider.ts +++ b/src/vs/workbench/contrib/url/common/trustedDomainsFileSystemProvider.ts @@ -33,8 +33,7 @@ const TRUSTED_DOMAINS_STAT: IStat = { size: 0 }; -const CONFIG_HELP_TEXT_PRE = - `// Links matching one or more entries in the list below can be opened without link protection. +const CONFIG_HELP_TEXT_PRE = `// Links matching one or more entries in the list below can be opened without link protection. // The following examples show what entries can look like: // - "https://microsoft.com": Matches this specific domain using https // - "https://*.microsoft.com": Match all domains ending in "microsoft.com" using https @@ -95,23 +94,36 @@ export class TrustedDomainsFileSystemProvider implements IFileSystemProvider, IW } readFile(resource: URI): Promise { - const { defaultTrustedDomains, trustedDomains } = readTrustedDomains(this.storageService, this.productService); + let trustedDomainsContent = this.storageService.get( + 'http.linkProtectionTrustedDomainsContent', + StorageScope.GLOBAL + ); + + if ( + !trustedDomainsContent || + trustedDomainsContent.indexOf(CONFIG_HELP_TEXT_PRE) === -1 || + trustedDomainsContent.indexOf(CONFIG_HELP_TEXT_AFTER) === -1 + ) { + const { defaultTrustedDomains, trustedDomains } = readTrustedDomains(this.storageService, this.productService); + + trustedDomainsContent = computeTrustedDomainContent(defaultTrustedDomains, trustedDomains); + } - const trustedDomainsContent = computeTrustedDomainContent(defaultTrustedDomains, trustedDomains); const buffer = VSBuffer.fromString(trustedDomainsContent).buffer; return Promise.resolve(buffer); } writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise { try { - const trustedDomains = parse(content.toString()); + const trustedDomainsContent = content.toString(); + const trustedDomains = parse(trustedDomainsContent); + this.storageService.store('http.linkProtectionTrustedDomainsContent', trustedDomainsContent, StorageScope.GLOBAL); this.storageService.store( 'http.linkProtectionTrustedDomains', JSON.stringify(trustedDomains), StorageScope.GLOBAL ); - } catch (err) { } return Promise.resolve(); From d4e49567f362ad5bde62e84f9037bb5e0ac6af53 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 3 Oct 2019 12:14:14 -0700 Subject: [PATCH 150/435] Update html language service --- extensions/html-language-features/server/package.json | 2 +- extensions/html-language-features/server/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index 58f9762e846..c11d21bbbd9 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -10,7 +10,7 @@ "main": "./out/htmlServerMain", "dependencies": { "vscode-css-languageservice": "^4.0.3-next.11", - "vscode-html-languageservice": "^3.0.4-next.5", + "vscode-html-languageservice": "^3.0.4-next.6", "vscode-languageserver": "^6.0.0-next.1", "vscode-languageserver-types": "3.15.0-next.5", "vscode-nls": "^4.1.1", diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index feed2d264a1..27c6f14811c 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -620,10 +620,10 @@ vscode-css-languageservice@^4.0.3-next.11: vscode-nls "^4.1.1" vscode-uri "^2.0.3" -vscode-html-languageservice@^3.0.4-next.5: - version "3.0.4-next.5" - resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.5.tgz#cf8bbb8deb80b06d43f41f485e0e6fdcaf6655ca" - integrity sha512-cEjWRRqO49nVIcaGkLrA4FY1CMPzIAFiK8QLY2hY/8lTX9ZxvGhuegY6MBQqyvLJyZPpWJ2yP9iWlMEPeX655A== +vscode-html-languageservice@^3.0.4-next.6: + version "3.0.4-next.6" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.6.tgz#ef0f535828f086bcf9bafb2609d54bb285d29d2a" + integrity sha512-DvFpvPJ9wGKIpNa6kxoUSRjZTzLadyKPO2rNhmU7oor9pAQbaNIdJBGoGCm3YELLLPFNcR0/jWDDC4z8wFPk3Q== dependencies: vscode-languageserver-types "^3.15.0-next.5" vscode-nls "^4.1.1" From 6a62058aae66e6a7fd1299ec34285ad43a1346e6 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 12:36:11 -0700 Subject: [PATCH 151/435] Cleanup dead code --- .../preferences/browser/keybindingsEditorContribution.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts index 9b45e34dee4..dc77efc7ce5 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts @@ -23,13 +23,11 @@ import { parseTree, Node } from 'vs/base/common/json'; import { ScanCodeBinding } from 'vs/base/common/scanCode'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { WindowsNativeResolvedKeybinding } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper'; -import { themeColorFromId, ThemeColor, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService'; import { overviewRulerInfo, overviewRulerError } from 'vs/editor/common/view/editorColorRegistry'; import { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/model'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeybindingParser } from 'vs/base/common/keybindingParser'; -import Severity from 'vs/base/common/severity'; -import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); @@ -399,8 +397,3 @@ function isInterestingEditorModel(editor: ICodeEditor): boolean { registerEditorContribution(DefineKeybindingController); registerEditorCommand(new DefineKeybindingCommand()); - -registerThemingParticipant((theme, collector) => { - collector.addRule(`.monaco-editor .inlineKeybindingInfo:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Info, theme)}") -0.1em -0.2em no-repeat; }`); - collector.addRule(`.monaco-editor .inlineKeybindingError:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Error, theme)}") -0.1em -0.2em no-repeat; }`); -}); From 56c2540154132af72b09de91616bea80f1d92066 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 12:37:10 -0700 Subject: [PATCH 152/435] Fix typo --- src/vs/platform/severityIcon/common/severityIcon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/severityIcon/common/severityIcon.ts b/src/vs/platform/severityIcon/common/severityIcon.ts index 98019496e51..b415e5d8786 100644 --- a/src/vs/platform/severityIcon/common/severityIcon.ts +++ b/src/vs/platform/severityIcon/common/severityIcon.ts @@ -24,7 +24,7 @@ export namespace SeverityIcon { } } -registerThemingParticipant((thme, collector) => { +registerThemingParticipant((theme, collector) => { const errorIconForeground = theme.getColor(problemsErrorIconForeground); if (errorIconForeground) { From 6e59411265c744d3fd103f508a895869aea15172 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 12:37:48 -0700 Subject: [PATCH 153/435] Add margin for peek icons --- .../editor/contrib/referenceSearch/media/peekViewWidget.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/referenceSearch/media/peekViewWidget.css b/src/vs/editor/contrib/referenceSearch/media/peekViewWidget.css index b0d1fefcf21..091c6cd70e7 100644 --- a/src/vs/editor/contrib/referenceSearch/media/peekViewWidget.css +++ b/src/vs/editor/contrib/referenceSearch/media/peekViewWidget.css @@ -60,3 +60,7 @@ border-top: 1px solid; position: relative; } + +.monaco-editor .peekview-widget .head .peekview-title .codicon { + margin-right: 4px; +} From ef698fa6cda44519cd7e5319aa657b8a4d1e2138 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Oct 2019 13:22:16 -0700 Subject: [PATCH 154/435] Make markdown refresh more stable Fixes #80680 - Always sync the current preview line number with the editor, even when `scrollEditorWithPreview` is false - If the md file is focused and refresh is called, do not try resetting the current line to match the editor file. This mainly effects the case where `scrollEditorWithPreview` is false --- .../markdown-language-features/media/index.js | 28 +++++++++---------- .../preview-src/index.ts | 24 ++++++++-------- .../src/features/preview.ts | 22 ++++++++++----- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/extensions/markdown-language-features/media/index.js b/extensions/markdown-language-features/media/index.js index 2111928ba3a..a17e886baff 100644 --- a/extensions/markdown-language-features/media/index.js +++ b/extensions/markdown-language-features/media/index.js @@ -767,21 +767,19 @@ document.addEventListener('click', event => { node = node.parentNode; } }, true); -if (settings.scrollEditorWithPreview) { - window.addEventListener('scroll', throttle(() => { - if (scrollDisabled) { - scrollDisabled = false; +window.addEventListener('scroll', throttle(() => { + if (scrollDisabled) { + scrollDisabled = false; + } + else { + const line = scroll_sync_1.getEditorLineNumberForPageOffset(window.scrollY); + if (typeof line === 'number' && !isNaN(line)) { + messaging.postMessage('revealLine', { line }); + state.line = line; + vscode.setState(state); } - else { - const line = scroll_sync_1.getEditorLineNumberForPageOffset(window.scrollY); - if (typeof line === 'number' && !isNaN(line)) { - messaging.postMessage('revealLine', { line }); - state.line = line; - vscode.setState(state); - } - } - }, 50)); -} + } +}, 50)); function escapeRegExp(text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } @@ -1009,4 +1007,4 @@ exports.getSettings = getSettings; /***/ }) /******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsTUFBTTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUI7QUFDcEU7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QywyQ0FBMkM7QUFDdkY7QUFDQSxvREFBb0QsaUJBQWlCO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxPQUFPO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7Ozs7Ozs7Ozs7Ozs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLGtDQUFrQztBQUMzRDtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMseUJBQXlCO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsaUJBQWlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLGlCQUFpQjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUN2SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxJQUFJO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSBcIi4vcHJldmlldy1zcmMvaW5kZXgudHNcIik7XG4iLCIvKipcbiAqIGxvZGFzaCAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIG1vZHVsYXJpemUgZXhwb3J0cz1cIm5wbVwiIC1vIC4vYFxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnMgPGh0dHBzOi8vanF1ZXJ5Lm9yZy8+XG4gKiBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9sb2Rhc2guY29tL2xpY2Vuc2U+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuOC4zIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4gKi9cblxuLyoqIFVzZWQgYXMgdGhlIGBUeXBlRXJyb3JgIG1lc3NhZ2UgZm9yIFwiRnVuY3Rpb25zXCIgbWV0aG9kcy4gKi9cbnZhciBGVU5DX0VSUk9SX1RFWFQgPSAnRXhwZWN0ZWQgYSBmdW5jdGlvbic7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIE5BTiA9IDAgLyAwO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UuICovXG52YXIgcmVUcmltID0gL15cXHMrfFxccyskL2c7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JhZEhleCA9IC9eWy0rXTB4WzAtOWEtZl0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmluYXJ5IHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG9jdGFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc09jdGFsID0gL14wb1swLTddKyQvaTtcblxuLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbnZhciBmcmVlUGFyc2VJbnQgPSBwYXJzZUludDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbnZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluO1xuXG4vKipcbiAqIEdldHMgdGhlIHRpbWVzdGFtcCBvZiB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZVxuICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAyLjQuMFxuICogQGNhdGVnb3J5IERhdGVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVzdGFtcC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5kZWZlcihmdW5jdGlvbihzdGFtcCkge1xuICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICogfSwgXy5ub3coKSk7XG4gKiAvLyA9PiBMb2dzIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGl0IHRvb2sgZm9yIHRoZSBkZWZlcnJlZCBpbnZvY2F0aW9uLlxuICovXG52YXIgbm93ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiByb290LkRhdGUubm93KCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gKiBpbnZva2VkLiBUaGUgZGVib3VuY2VkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYCBtZXRob2QgdG8gY2FuY2VsXG4gKiBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0byBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS5cbiAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICogbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICogd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbi4gU3Vic2VxdWVudFxuICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAqIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8uZGVib3VuY2VgIGFuZCBgXy50aHJvdHRsZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XVxuICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXguXG4gKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICpcbiAqIC8vIEludm9rZSBgc2VuZE1haWxgIHdoZW4gY2xpY2tlZCwgZGVib3VuY2luZyBzdWJzZXF1ZW50IGNhbGxzLlxuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICogICAnbGVhZGluZyc6IHRydWUsXG4gKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gKiB9KSk7XG4gKlxuICogLy8gRW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxscy5cbiAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICogdmFyIHNvdXJjZSA9IG5ldyBFdmVudFNvdXJjZSgnL3N0cmVhbScpO1xuICogalF1ZXJ5KHNvdXJjZSkub24oJ21lc3NhZ2UnLCBkZWJvdW5jZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGFzdEFyZ3MsXG4gICAgICBsYXN0VGhpcyxcbiAgICAgIG1heFdhaXQsXG4gICAgICByZXN1bHQsXG4gICAgICB0aW1lcklkLFxuICAgICAgbGFzdENhbGxUaW1lLFxuICAgICAgbGFzdEludm9rZVRpbWUgPSAwLFxuICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgbWF4aW5nID0gZmFsc2UsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICBtYXhXYWl0ID0gbWF4aW5nID8gbmF0aXZlTWF4KHRvTnVtYmVyKG9wdGlvbnMubWF4V2FpdCkgfHwgMCwgd2FpdCkgOiBtYXhXYWl0O1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cblxuICBmdW5jdGlvbiBpbnZva2VGdW5jKHRpbWUpIHtcbiAgICB2YXIgYXJncyA9IGxhc3RBcmdzLFxuICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgLy8gUmVzZXQgYW55IGBtYXhXYWl0YCB0aW1lci5cbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbWFpbmluZ1dhaXQodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWUsXG4gICAgICAgIHJlc3VsdCA9IHdhaXQgLSB0aW1lU2luY2VMYXN0Q2FsbDtcblxuICAgIHJldHVybiBtYXhpbmcgPyBuYXRpdmVNaW4ocmVzdWx0LCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBzaG91bGRJbnZva2UodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWU7XG5cbiAgICAvLyBFaXRoZXIgdGhpcyBpcyB0aGUgZmlyc3QgY2FsbCwgYWN0aXZpdHkgaGFzIHN0b3BwZWQgYW5kIHdlJ3JlIGF0IHRoZVxuICAgIC8vIHRyYWlsaW5nIGVkZ2UsIHRoZSBzeXN0ZW0gdGltZSBoYXMgZ29uZSBiYWNrd2FyZHMgYW5kIHdlJ3JlIHRyZWF0aW5nXG4gICAgLy8gaXQgYXMgdGhlIHRyYWlsaW5nIGVkZ2UsIG9yIHdlJ3ZlIGhpdCB0aGUgYG1heFdhaXRgIGxpbWl0LlxuICAgIHJldHVybiAobGFzdENhbGxUaW1lID09PSB1bmRlZmluZWQgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXJFeHBpcmVkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCk7XG4gICAgaWYgKHNob3VsZEludm9rZSh0aW1lKSkge1xuICAgICAgcmV0dXJuIHRyYWlsaW5nRWRnZSh0aW1lKTtcbiAgICB9XG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYWlsaW5nRWRnZSh0aW1lKSB7XG4gICAgdGltZXJJZCA9IHVuZGVmaW5lZDtcblxuICAgIC8vIE9ubHkgaW52b2tlIGlmIHdlIGhhdmUgYGxhc3RBcmdzYCB3aGljaCBtZWFucyBgZnVuY2AgaGFzIGJlZW5cbiAgICAvLyBkZWJvdW5jZWQgYXQgbGVhc3Qgb25jZS5cbiAgICBpZiAodHJhaWxpbmcgJiYgbGFzdEFyZ3MpIHtcbiAgICAgIHJldHVybiBpbnZva2VGdW5jKHRpbWUpO1xuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgaWYgKHRpbWVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDA7XG4gICAgbGFzdEFyZ3MgPSBsYXN0Q2FsbFRpbWUgPSBsYXN0VGhpcyA9IHRpbWVySWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICByZXR1cm4gdGltZXJJZCA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKG5vdygpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpLFxuICAgICAgICBpc0ludm9raW5nID0gc2hvdWxkSW52b2tlKHRpbWUpO1xuXG4gICAgbGFzdEFyZ3MgPSBhcmd1bWVudHM7XG4gICAgbGFzdFRoaXMgPSB0aGlzO1xuICAgIGxhc3RDYWxsVGltZSA9IHRpbWU7XG5cbiAgICBpZiAoaXNJbnZva2luZykge1xuICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICAgIGlmIChtYXhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIGludm9jYXRpb25zIGluIGEgdGlnaHQgbG9vcC5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgcmV0dXJuIGludm9rZUZ1bmMobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBkZWJvdW5jZWQuY2FuY2VsID0gY2FuY2VsO1xuICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgcmV0dXJuIGRlYm91bmNlZDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgdGhyb3R0bGVkIGZ1bmN0aW9uIHRoYXQgb25seSBpbnZva2VzIGBmdW5jYCBhdCBtb3N0IG9uY2UgcGVyXG4gKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICogbWV0aG9kIHRvIGNhbmNlbCBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0b1xuICogaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgXG4gKiBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgXG4gKiB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWQgd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlXG4gKiB0aHJvdHRsZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnQgY2FsbHMgdG8gdGhlIHRocm90dGxlZCBmdW5jdGlvbiByZXR1cm4gdGhlXG4gKiByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8udGhyb3R0bGVgIGFuZCBgXy5kZWJvdW5jZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBpbnZvY2F0aW9ucyB0by5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB0aHJvdHRsZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGV4Y2Vzc2l2ZWx5IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBzY3JvbGxpbmcuXG4gKiBqUXVlcnkod2luZG93KS5vbignc2Nyb2xsJywgXy50aHJvdHRsZSh1cGRhdGVQb3NpdGlvbiwgMTAwKSk7XG4gKlxuICogLy8gSW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXMuXG4gKiB2YXIgdGhyb3R0bGVkID0gXy50aHJvdHRsZShyZW5ld1Rva2VuLCAzMDAwMDAsIHsgJ3RyYWlsaW5nJzogZmFsc2UgfSk7XG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdGhyb3R0bGVkKTtcbiAqXG4gKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIHRocm90dGxlZCBpbnZvY2F0aW9uLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgdGhyb3R0bGVkLmNhbmNlbCk7XG4gKi9cbmZ1bmN0aW9uIHRocm90dGxlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgdmFyIGxlYWRpbmcgPSB0cnVlLFxuICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICB9XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAnbGVhZGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy5sZWFkaW5nIDogbGVhZGluZztcbiAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICB9XG4gIHJldHVybiBkZWJvdW5jZShmdW5jLCB3YWl0LCB7XG4gICAgJ2xlYWRpbmcnOiBsZWFkaW5nLFxuICAgICdtYXhXYWl0Jzogd2FpdCxcbiAgICAndHJhaWxpbmcnOiB0cmFpbGluZ1xuICB9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAhIXZhbHVlICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdExpa2Uoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgcmV0dXJuICEhdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3ltYm9sLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNTeW1ib2woU3ltYm9sLml0ZXJhdG9yKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzU3ltYm9sKCdhYmMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N5bWJvbCcgfHxcbiAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBudW1iZXIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8udG9OdW1iZXIoMy4yKTtcbiAqIC8vID0+IDMuMlxuICpcbiAqIF8udG9OdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gKiAvLyA9PiA1ZS0zMjRcbiAqXG4gKiBfLnRvTnVtYmVyKEluZmluaXR5KTtcbiAqIC8vID0+IEluZmluaXR5XG4gKlxuICogXy50b051bWJlcignMy4yJyk7XG4gKiAvLyA9PiAzLjJcbiAqL1xuZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgcmV0dXJuIE5BTjtcbiAgfVxuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgdmFyIG90aGVyID0gdHlwZW9mIHZhbHVlLnZhbHVlT2YgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgIHZhbHVlID0gaXNPYmplY3Qob3RoZXIpID8gKG90aGVyICsgJycpIDogb3RoZXI7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogK3ZhbHVlO1xuICB9XG4gIHZhbHVlID0gdmFsdWUucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgcmV0dXJuIChpc0JpbmFyeSB8fCByZUlzT2N0YWwudGVzdCh2YWx1ZSkpXG4gICAgPyBmcmVlUGFyc2VJbnQodmFsdWUuc2xpY2UoMiksIGlzQmluYXJ5ID8gMiA6IDgpXG4gICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdGhyb3R0bGU7XG4iLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSwgZXZhbCkoXCJ0aGlzXCIpO1xyXG59IGNhdGNoIChlKSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcclxuXHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIikgZyA9IHdpbmRvdztcclxufVxyXG5cclxuLy8gZyBjYW4gc3RpbGwgYmUgdW5kZWZpbmVkLCBidXQgbm90aGluZyB0byBkbyBhYm91dCBpdC4uLlxyXG4vLyBXZSByZXR1cm4gdW5kZWZpbmVkLCBpbnN0ZWFkIG9mIG5vdGhpbmcgaGVyZSwgc28gaXQnc1xyXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGc7XHJcbiIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5jb25zdCBzY3JvbGxfc3luY18xID0gcmVxdWlyZShcIi4vc2Nyb2xsLXN5bmNcIik7XG5jbGFzcyBBY3RpdmVMaW5lTWFya2VyIHtcbiAgICBvbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24obGluZSkge1xuICAgICAgICBjb25zdCB7IHByZXZpb3VzIH0gPSBzY3JvbGxfc3luY18xLmdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKHByZXZpb3VzICYmIHByZXZpb3VzLmVsZW1lbnQpO1xuICAgIH1cbiAgICBfdXBkYXRlKGJlZm9yZSkge1xuICAgICAgICB0aGlzLl91bm1hcmtBY3RpdmVFbGVtZW50KHRoaXMuX2N1cnJlbnQpO1xuICAgICAgICB0aGlzLl9tYXJrQWN0aXZlRWxlbWVudChiZWZvcmUpO1xuICAgICAgICB0aGlzLl9jdXJyZW50ID0gYmVmb3JlO1xuICAgIH1cbiAgICBfdW5tYXJrQWN0aXZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUucmVwbGFjZSgvXFxiY29kZS1hY3RpdmUtbGluZVxcYi9nLCAnJyk7XG4gICAgfVxuICAgIF9tYXJrQWN0aXZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lICs9ICcgY29kZS1hY3RpdmUtbGluZSc7XG4gICAgfVxufVxuZXhwb3J0cy5BY3RpdmVMaW5lTWFya2VyID0gQWN0aXZlTGluZU1hcmtlcjtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiBvbmNlRG9jdW1lbnRMb2FkZWQoZikge1xuICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ3VuaW5pdGlhbGl6ZWQnKSB7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGYoKTtcbiAgICB9XG59XG5leHBvcnRzLm9uY2VEb2N1bWVudExvYWRlZCA9IG9uY2VEb2N1bWVudExvYWRlZDtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBhY3RpdmVMaW5lTWFya2VyXzEgPSByZXF1aXJlKFwiLi9hY3RpdmVMaW5lTWFya2VyXCIpO1xuY29uc3QgZXZlbnRzXzEgPSByZXF1aXJlKFwiLi9ldmVudHNcIik7XG5jb25zdCBtZXNzYWdpbmdfMSA9IHJlcXVpcmUoXCIuL21lc3NhZ2luZ1wiKTtcbmNvbnN0IHNjcm9sbF9zeW5jXzEgPSByZXF1aXJlKFwiLi9zY3JvbGwtc3luY1wiKTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmNvbnN0IHRocm90dGxlID0gcmVxdWlyZShcImxvZGFzaC50aHJvdHRsZVwiKTtcbmxldCBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG5jb25zdCBtYXJrZXIgPSBuZXcgYWN0aXZlTGluZU1hcmtlcl8xLkFjdGl2ZUxpbmVNYXJrZXIoKTtcbmNvbnN0IHNldHRpbmdzID0gc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpO1xuY29uc3QgdnNjb2RlID0gYWNxdWlyZVZzQ29kZUFwaSgpO1xuLy8gU2V0IFZTIENvZGUgc3RhdGVcbmxldCBzdGF0ZSA9IHNldHRpbmdzXzEuZ2V0RGF0YSgnZGF0YS1zdGF0ZScpO1xudnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcbmNvbnN0IG1lc3NhZ2luZyA9IG1lc3NhZ2luZ18xLmNyZWF0ZVBvc3RlckZvclZzQ29kZSh2c2NvZGUpO1xud2luZG93LmNzcEFsZXJ0ZXIuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG53aW5kb3cuc3R5bGVMb2FkaW5nTW9uaXRvci5zZXRQb3N0ZXIobWVzc2FnaW5nKTtcbndpbmRvdy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgdXBkYXRlSW1hZ2VTaXplcygpO1xufTtcbmV2ZW50c18xLm9uY2VEb2N1bWVudExvYWRlZCgoKSA9PiB7XG4gICAgaWYgKHNldHRpbmdzLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgLy8gVHJ5IHRvIHNjcm9sbCB0byBmcmFnbWVudCBpZiBhdmFpbGFibGVcbiAgICAgICAgICAgIGlmIChzdGF0ZS5mcmFnbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBzY3JvbGxfc3luY18xLmdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQoc3RhdGUuZnJhZ21lbnQpO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUoZWxlbWVudC5saW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbml0aWFsTGluZSA9ICtzZXR0aW5ncy5saW5lO1xuICAgICAgICAgICAgICAgIGlmICghaXNOYU4oaW5pdGlhbExpbmUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUoaW5pdGlhbExpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgMCk7XG4gICAgfVxufSk7XG5jb25zdCBvblVwZGF0ZVZpZXcgPSAoKCkgPT4ge1xuICAgIGNvbnN0IGRvU2Nyb2xsID0gdGhyb3R0bGUoKGxpbmUpID0+IHtcbiAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKTtcbiAgICB9LCA1MCk7XG4gICAgcmV0dXJuIChsaW5lLCBzZXR0aW5ncykgPT4ge1xuICAgICAgICBpZiAoIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgICAgICBzZXR0aW5ncy5saW5lID0gbGluZTtcbiAgICAgICAgICAgIGRvU2Nyb2xsKGxpbmUpO1xuICAgICAgICB9XG4gICAgfTtcbn0pKCk7XG5sZXQgdXBkYXRlSW1hZ2VTaXplcyA9IHRocm90dGxlKCgpID0+IHtcbiAgICBjb25zdCBpbWFnZUluZm8gPSBbXTtcbiAgICBsZXQgaW1hZ2VzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2ltZycpO1xuICAgIGlmIChpbWFnZXMpIHtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGltZyA9IGltYWdlc1tpXTtcbiAgICAgICAgICAgIGlmIChpbWcuY2xhc3NMaXN0LmNvbnRhaW5zKCdsb2FkaW5nJykpIHtcbiAgICAgICAgICAgICAgICBpbWcuY2xhc3NMaXN0LnJlbW92ZSgnbG9hZGluZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW1hZ2VJbmZvLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBpbWcuaWQsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpbWcuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBpbWcud2lkdGhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnY2FjaGVJbWFnZVNpemVzJywgaW1hZ2VJbmZvKTtcbiAgICB9XG59LCA1MCk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgKCkgPT4ge1xuICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICB1cGRhdGVJbWFnZVNpemVzKCk7XG59LCB0cnVlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZXZlbnQgPT4ge1xuICAgIGlmIChldmVudC5kYXRhLnNvdXJjZSAhPT0gc2V0dGluZ3Muc291cmNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoIChldmVudC5kYXRhLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnb25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uJzpcbiAgICAgICAgICAgIG1hcmtlci5vbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24oZXZlbnQuZGF0YS5saW5lKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1cGRhdGVWaWV3JzpcbiAgICAgICAgICAgIG9uVXBkYXRlVmlldyhldmVudC5kYXRhLmxpbmUsIHNldHRpbmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbn0sIGZhbHNlKTtcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgZXZlbnQgPT4ge1xuICAgIGlmICghc2V0dGluZ3MuZG91YmxlQ2xpY2tUb1N3aXRjaFRvRWRpdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gSWdub3JlIGNsaWNrcyBvbiBsaW5rc1xuICAgIGZvciAobGV0IG5vZGUgPSBldmVudC50YXJnZXQ7IG5vZGU7IG5vZGUgPSBub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUudGFnTmFtZSA9PT0gJ0EnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgb2Zmc2V0ID0gZXZlbnQucGFnZVk7XG4gICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KTtcbiAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2RpZENsaWNrJywgeyBsaW5lOiBNYXRoLmZsb29yKGxpbmUpIH0pO1xuICAgIH1cbn0pO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBldmVudCA9PiB7XG4gICAgaWYgKCFldmVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBub2RlID0gZXZlbnQudGFyZ2V0O1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgIGlmIChub2RlLnRhZ05hbWUgJiYgbm9kZS50YWdOYW1lID09PSAnQScgJiYgbm9kZS5ocmVmKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKS5zdGFydHNXaXRoKCcjJykpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub2RlLmhyZWYuc3RhcnRzV2l0aCgnZmlsZTovLycpIHx8IG5vZGUuaHJlZi5zdGFydHNXaXRoKCd2c2NvZGUtcmVzb3VyY2U6JykgfHwgbm9kZS5ocmVmLnN0YXJ0c1dpdGgoc2V0dGluZ3Mud2Vidmlld1Jlc291cmNlUm9vdCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBbcGF0aCwgZnJhZ21lbnRdID0gbm9kZS5ocmVmXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eZmlsZTpcXC9cXC8vaSwgJycpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9ednNjb2RlLXJlc291cmNlOlxcL1xcL1teXFwvXStcXC8vaSwgJycpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4ke2VzY2FwZVJlZ0V4cChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KX1gKSlcbiAgICAgICAgICAgICAgICAgICAgLnNwbGl0KCcjJyk7XG4gICAgICAgICAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjbGlja0xpbmsnLCB7IHBhdGgsIGZyYWdtZW50IH0pO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgIH1cbn0sIHRydWUpO1xuaWYgKHNldHRpbmdzLnNjcm9sbEVkaXRvcldpdGhQcmV2aWV3KSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRocm90dGxlKCgpID0+IHtcbiAgICAgICAgaWYgKHNjcm9sbERpc2FibGVkKSB7XG4gICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ3JldmVhbExpbmUnLCB7IGxpbmUgfSk7XG4gICAgICAgICAgICAgICAgc3RhdGUubGluZSA9IGxpbmU7XG4gICAgICAgICAgICAgICAgdnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIDUwKSk7XG59XG5mdW5jdGlvbiBlc2NhcGVSZWdFeHAodGV4dCkge1xuICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL1stW1xcXXt9KCkqKz8uLFxcXFxeJHwjXFxzXS9nLCAnXFxcXCQmJyk7XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuZXhwb3J0cy5jcmVhdGVQb3N0ZXJGb3JWc0NvZGUgPSAodnNjb2RlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBjbGFzcyB7XG4gICAgICAgIHBvc3RNZXNzYWdlKHR5cGUsIGJvZHkpIHtcbiAgICAgICAgICAgIHZzY29kZS5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICBzb3VyY2U6IHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKS5zb3VyY2UsXG4gICAgICAgICAgICAgICAgYm9keVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5mdW5jdGlvbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpIHtcbiAgICByZXR1cm4gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIHZhbHVlKSk7XG59XG5mdW5jdGlvbiBjbGFtcExpbmUobGluZSkge1xuICAgIHJldHVybiBjbGFtcCgwLCBzZXR0aW5nc18xLmdldFNldHRpbmdzKCkubGluZUNvdW50IC0gMSwgbGluZSk7XG59XG5jb25zdCBnZXRDb2RlTGluZUVsZW1lbnRzID0gKCgpID0+IHtcbiAgICBsZXQgZWxlbWVudHM7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgaWYgKCFlbGVtZW50cykge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBbeyBlbGVtZW50OiBkb2N1bWVudC5ib2R5LCBsaW5lOiAwIH1dO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2NvZGUtbGluZScpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGluZSA9ICtlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1saW5lJyk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50cy5wdXNoKHsgZWxlbWVudDogZWxlbWVudCwgbGluZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsZW1lbnRzO1xuICAgIH07XG59KSgpO1xuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgbWFwIHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxpbmUgaW4gdGhlIGVkaXRvci5cbiAqXG4gKiBJZiBhbiBleGFjdCBtYXRjaCwgcmV0dXJucyBhIHNpbmdsZSBlbGVtZW50LiBJZiB0aGUgbGluZSBpcyBiZXR3ZWVuIGVsZW1lbnRzLFxuICogcmV0dXJucyB0aGUgZWxlbWVudCBwcmlvciB0byBhbmQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGdpdmVuIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGdldEVsZW1lbnRzRm9yU291cmNlTGluZSh0YXJnZXRMaW5lKSB7XG4gICAgY29uc3QgbGluZU51bWJlciA9IE1hdGguZmxvb3IodGFyZ2V0TGluZSk7XG4gICAgY29uc3QgbGluZXMgPSBnZXRDb2RlTGluZUVsZW1lbnRzKCk7XG4gICAgbGV0IHByZXZpb3VzID0gbGluZXNbMF0gfHwgbnVsbDtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGxpbmVzKSB7XG4gICAgICAgIGlmIChlbnRyeS5saW5lID09PSBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91czogZW50cnksIG5leHQ6IHVuZGVmaW5lZCB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGVudHJ5LmxpbmUgPiBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91cywgbmV4dDogZW50cnkgfTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2aW91cyA9IGVudHJ5O1xuICAgIH1cbiAgICByZXR1cm4geyBwcmV2aW91cyB9O1xufVxuZXhwb3J0cy5nZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUgPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmU7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBhcmUgYXQgYSBzcGVjaWZpYyBwaXhlbCBvZmZzZXQgb24gdGhlIHBhZ2UuXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpIHtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBjb25zdCBwb3NpdGlvbiA9IG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZO1xuICAgIGxldCBsbyA9IC0xO1xuICAgIGxldCBoaSA9IGxpbmVzLmxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKGxvICsgMSA8IGhpKSB7XG4gICAgICAgIGNvbnN0IG1pZCA9IE1hdGguZmxvb3IoKGxvICsgaGkpIC8gMik7XG4gICAgICAgIGNvbnN0IGJvdW5kcyA9IGxpbmVzW21pZF0uZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaWYgKGJvdW5kcy50b3AgKyBib3VuZHMuaGVpZ2h0ID49IHBvc2l0aW9uKSB7XG4gICAgICAgICAgICBoaSA9IG1pZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxvID0gbWlkO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGhpRWxlbWVudCA9IGxpbmVzW2hpXTtcbiAgICBjb25zdCBoaUJvdW5kcyA9IGhpRWxlbWVudC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChoaSA+PSAxICYmIGhpQm91bmRzLnRvcCA+IHBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IGxvRWxlbWVudCA9IGxpbmVzW2xvXTtcbiAgICAgICAgcmV0dXJuIHsgcHJldmlvdXM6IGxvRWxlbWVudCwgbmV4dDogaGlFbGVtZW50IH07XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzOiBoaUVsZW1lbnQgfTtcbn1cbmV4cG9ydHMuZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0O1xuLyoqXG4gKiBBdHRlbXB0IHRvIHJldmVhbCB0aGUgZWxlbWVudCBmb3IgYSBzb3VyY2UgbGluZSBpbiB0aGUgZWRpdG9yLlxuICovXG5mdW5jdGlvbiBzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSkge1xuICAgIGlmICghc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGxpbmUgPD0gMCkge1xuICAgICAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB7IHByZXZpb3VzLCBuZXh0IH0gPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG4gICAgaWYgKCFwcmV2aW91cykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBzY3JvbGxUbyA9IDA7XG4gICAgY29uc3QgcmVjdCA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgcHJldmlvdXNUb3AgPSByZWN0LnRvcDtcbiAgICBpZiAobmV4dCAmJiBuZXh0LmxpbmUgIT09IHByZXZpb3VzLmxpbmUpIHtcbiAgICAgICAgLy8gQmV0d2VlbiB0d28gZWxlbWVudHMuIEdvIHRvIHBlcmNlbnRhZ2Ugb2Zmc2V0IGJldHdlZW4gdGhlbS5cbiAgICAgICAgY29uc3QgYmV0d2VlblByb2dyZXNzID0gKGxpbmUgLSBwcmV2aW91cy5saW5lKSAvIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgY29uc3QgZWxlbWVudE9mZnNldCA9IG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c1RvcDtcbiAgICAgICAgc2Nyb2xsVG8gPSBwcmV2aW91c1RvcCArIGJldHdlZW5Qcm9ncmVzcyAqIGVsZW1lbnRPZmZzZXQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBwcm9ncmVzc0luRWxlbWVudCA9IGxpbmUgLSBNYXRoLmZsb29yKGxpbmUpO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgKHJlY3QuaGVpZ2h0ICogcHJvZ3Jlc3NJbkVsZW1lbnQpO1xuICAgIH1cbiAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCBNYXRoLm1heCgxLCB3aW5kb3cuc2Nyb2xsWSArIHNjcm9sbFRvKSk7XG59XG5leHBvcnRzLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZSA9IHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZTtcbmZ1bmN0aW9uIGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpO1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICBjb25zdCBwcmV2aW91c0JvdW5kcyA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IG9mZnNldEZyb21QcmV2aW91cyA9IChvZmZzZXQgLSB3aW5kb3cuc2Nyb2xsWSAtIHByZXZpb3VzQm91bmRzLnRvcCk7XG4gICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyA9IG9mZnNldEZyb21QcmV2aW91cyAvIChuZXh0LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NCZXR3ZWVuRWxlbWVudHMgKiAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG4gICAgICAgICAgICByZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50ID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKHByZXZpb3VzQm91bmRzLmhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gcHJldmlvdXMubGluZSArIHByb2dyZXNzV2l0aGluRWxlbWVudDtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5leHBvcnRzLmdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0ID0gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQ7XG4vKipcbiAqIFRyeSB0byBmaW5kIHRoZSBodG1sIGVsZW1lbnQgYnkgdXNpbmcgYSBmcmFnbWVudCBpZFxuICovXG5mdW5jdGlvbiBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50KGZyYWdtZW50KSB7XG4gICAgcmV0dXJuIGdldENvZGVMaW5lRWxlbWVudHMoKS5maW5kKChlbGVtZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBlbGVtZW50LmVsZW1lbnQuaWQgPT09IGZyYWdtZW50O1xuICAgIH0pO1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudEZvckZyYWdtZW50ID0gZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudDtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sZXQgY2FjaGVkU2V0dGluZ3MgPSB1bmRlZmluZWQ7XG5mdW5jdGlvbiBnZXREYXRhKGtleSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndnNjb2RlLW1hcmtkb3duLXByZXZpZXctZGF0YScpO1xuICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBkYXRhIGZvciAke2tleX1gKTtcbn1cbmV4cG9ydHMuZ2V0RGF0YSA9IGdldERhdGE7XG5mdW5jdGlvbiBnZXRTZXR0aW5ncygpIHtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICBjYWNoZWRTZXR0aW5ncyA9IGdldERhdGEoJ2RhdGEtc2V0dGluZ3MnKTtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHNldHRpbmdzJyk7XG59XG5leHBvcnRzLmdldFNldHRpbmdzID0gZ2V0U2V0dGluZ3M7XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsTUFBTTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUI7QUFDcEU7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QywyQ0FBMkM7QUFDdkY7QUFDQSxvREFBb0QsaUJBQWlCO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsT0FBTztBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBLGdDQUFnQztBQUNoQzs7Ozs7Ozs7Ozs7OztBQ3ZKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsa0NBQWtDO0FBQzNEO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyx5QkFBeUI7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxpQkFBaUI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsaUJBQWlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7Ozs7Ozs7Ozs7OztBQ3ZJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLElBQUk7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9wcmV2aWV3LXNyYy9pbmRleC50c1wiKTtcbiIsIi8qKlxuICogbG9kYXNoIChDdXN0b20gQnVpbGQpIDxodHRwczovL2xvZGFzaC5jb20vPlxuICogQnVpbGQ6IGBsb2Rhc2ggbW9kdWxhcml6ZSBleHBvcnRzPVwibnBtXCIgLW8gLi9gXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyA8aHR0cHM6Ly9qcXVlcnkub3JnLz5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbiAqL1xuXG4vKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG52YXIgTkFOID0gMCAvIDA7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxuLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbnZhciByZVRyaW0gPSAvXlxccyt8XFxzKyQvZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJhZCBzaWduZWQgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiaW5hcnkgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmluYXJ5ID0gL14wYlswMV0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzT2N0YWwgPSAvXjBvWzAtN10rJC9pO1xuXG4vKiogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgd2l0aG91dCBhIGRlcGVuZGVuY3kgb24gYHJvb3RgLiAqL1xudmFyIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xudmFyIGZyZWVTZWxmID0gdHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZiAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHNlbGY7XG5cbi8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xudmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZVxuICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gKiBvZiB2YWx1ZXMuXG4gKi9cbnZhciBvYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgbmF0aXZlTWluID0gTWF0aC5taW47XG5cbi8qKlxuICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDIuNC4wXG4gKiBAY2F0ZWdvcnkgRGF0ZVxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gKiB9LCBfLm5vdygpKTtcbiAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gKi9cbnZhciBub3cgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHJvb3QuRGF0ZS5ub3coKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gKiBtaWxsaXNlY29uZHMgaGF2ZSBlbGFwc2VkIHNpbmNlIHRoZSBsYXN0IHRpbWUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiB3YXNcbiAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICogUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb24gdGhlXG4gKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gKiBjYWxscyB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYFxuICogaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5LlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm1heFdhaXRdXG4gKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdyZXNpemUnLCBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSk7XG4gKlxuICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5kZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAqIH0pKTtcbiAqXG4gKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICogdmFyIGRlYm91bmNlZCA9IF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwgeyAnbWF4V2FpdCc6IDEwMDAgfSk7XG4gKiB2YXIgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJyk7XG4gKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyBkZWJvdW5jZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsYXN0QXJncyxcbiAgICAgIGxhc3RUaGlzLFxuICAgICAgbWF4V2FpdCxcbiAgICAgIHJlc3VsdCxcbiAgICAgIHRpbWVySWQsXG4gICAgICBsYXN0Q2FsbFRpbWUsXG4gICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICBsZWFkaW5nID0gZmFsc2UsXG4gICAgICBtYXhpbmcgPSBmYWxzZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB3YWl0ID0gdG9OdW1iZXIod2FpdCkgfHwgMDtcbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgIG1heGluZyA9ICdtYXhXYWl0JyBpbiBvcHRpb25zO1xuICAgIG1heFdhaXQgPSBtYXhpbmcgPyBuYXRpdmVNYXgodG9OdW1iZXIob3B0aW9ucy5tYXhXYWl0KSB8fCAwLCB3YWl0KSA6IG1heFdhaXQ7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuXG4gIGZ1bmN0aW9uIGludm9rZUZ1bmModGltZSkge1xuICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgIHRoaXNBcmcgPSBsYXN0VGhpcztcblxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxlYWRpbmdFZGdlKHRpbWUpIHtcbiAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAvLyBTdGFydCB0aGUgdGltZXIgZm9yIHRoZSB0cmFpbGluZyBlZGdlLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgcmV0dXJuIGxlYWRpbmcgPyBpbnZva2VGdW5jKHRpbWUpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZSxcbiAgICAgICAgcmVzdWx0ID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgcmV0dXJuIG1heGluZyA/IG5hdGl2ZU1pbihyZXN1bHQsIG1heFdhaXQgLSB0aW1lU2luY2VMYXN0SW52b2tlKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZTtcblxuICAgIC8vIEVpdGhlciB0aGlzIGlzIHRoZSBmaXJzdCBjYWxsLCBhY3Rpdml0eSBoYXMgc3RvcHBlZCBhbmQgd2UncmUgYXQgdGhlXG4gICAgLy8gdHJhaWxpbmcgZWRnZSwgdGhlIHN5c3RlbSB0aW1lIGhhcyBnb25lIGJhY2t3YXJkcyBhbmQgd2UncmUgdHJlYXRpbmdcbiAgICAvLyBpdCBhcyB0aGUgdHJhaWxpbmcgZWRnZSwgb3Igd2UndmUgaGl0IHRoZSBgbWF4V2FpdGAgbGltaXQuXG4gICAgcmV0dXJuIChsYXN0Q2FsbFRpbWUgPT09IHVuZGVmaW5lZCB8fCAodGltZVNpbmNlTGFzdENhbGwgPj0gd2FpdCkgfHxcbiAgICAgICh0aW1lU2luY2VMYXN0Q2FsbCA8IDApIHx8IChtYXhpbmcgJiYgdGltZVNpbmNlTGFzdEludm9rZSA+PSBtYXhXYWl0KSk7XG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKTtcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpO1xuICAgIH1cbiAgICAvLyBSZXN0YXJ0IHRoZSB0aW1lci5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHJlbWFpbmluZ1dhaXQodGltZSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gT25seSBpbnZva2UgaWYgd2UgaGF2ZSBgbGFzdEFyZ3NgIHdoaWNoIG1lYW5zIGBmdW5jYCBoYXMgYmVlblxuICAgIC8vIGRlYm91bmNlZCBhdCBsZWFzdCBvbmNlLlxuICAgIGlmICh0cmFpbGluZyAmJiBsYXN0QXJncykge1xuICAgICAgcmV0dXJuIGludm9rZUZ1bmModGltZSk7XG4gICAgfVxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfVxuICAgIGxhc3RJbnZva2VUaW1lID0gMDtcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgIHJldHVybiB0aW1lcklkID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiB0cmFpbGluZ0VkZ2Uobm93KCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCksXG4gICAgICAgIGlzSW52b2tpbmcgPSBzaG91bGRJbnZva2UodGltZSk7XG5cbiAgICBsYXN0QXJncyA9IGFyZ3VtZW50cztcbiAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgbGFzdENhbGxUaW1lID0gdGltZTtcblxuICAgIGlmIChpc0ludm9raW5nKSB7XG4gICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBsZWFkaW5nRWRnZShsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICByZXR1cm4gaW52b2tlRnVuYyhsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gIGRlYm91bmNlZC5mbHVzaCA9IGZsdXNoO1xuICByZXR1cm4gZGVib3VuY2VkO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAqIGV2ZXJ5IGB3YWl0YCBtaWxsaXNlY29uZHMuIFRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgXG4gKiBtZXRob2QgdG8gY2FuY2VsIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvXG4gKiBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS4gUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2BcbiAqIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGBcbiAqIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZCB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGVcbiAqIHRocm90dGxlZCBmdW5jdGlvbi4gU3Vic2VxdWVudCBjYWxscyB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHJldHVybiB0aGVcbiAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRocm90dGxlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy50aHJvdHRsZWAgYW5kIGBfLmRlYm91bmNlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHRocm90dGxlIGludm9jYXRpb25zIHRvLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHRocm90dGxlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgZXhjZXNzaXZlbHkgdXBkYXRpbmcgdGhlIHBvc2l0aW9uIHdoaWxlIHNjcm9sbGluZy5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdzY3JvbGwnLCBfLnRocm90dGxlKHVwZGF0ZVBvc2l0aW9uLCAxMDApKTtcbiAqXG4gKiAvLyBJbnZva2UgYHJlbmV3VG9rZW5gIHdoZW4gdGhlIGNsaWNrIGV2ZW50IGlzIGZpcmVkLCBidXQgbm90IG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IDUgbWludXRlcy5cbiAqIHZhciB0aHJvdHRsZWQgPSBfLnRocm90dGxlKHJlbmV3VG9rZW4sIDMwMDAwMCwgeyAndHJhaWxpbmcnOiBmYWxzZSB9KTtcbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCB0aHJvdHRsZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgdGhyb3R0bGVkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCB0aHJvdHRsZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cbiAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHtcbiAgICAnbGVhZGluZyc6IGxlYWRpbmcsXG4gICAgJ21heFdhaXQnOiB3YWl0LFxuICAgICd0cmFpbGluZyc6IHRyYWlsaW5nXG4gIH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHN5bWJvbFRhZyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIG51bWJlci5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAqIEBleGFtcGxlXG4gKlxuICogXy50b051bWJlcigzLjIpO1xuICogLy8gPT4gMy4yXG4gKlxuICogXy50b051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAqIC8vID0+IDVlLTMyNFxuICpcbiAqIF8udG9OdW1iZXIoSW5maW5pdHkpO1xuICogLy8gPT4gSW5maW5pdHlcbiAqXG4gKiBfLnRvTnVtYmVyKCczLjInKTtcbiAqIC8vID0+IDMuMlxuICovXG5mdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gTkFOO1xuICB9XG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICB2YXIgb3RoZXIgPSB0eXBlb2YgdmFsdWUudmFsdWVPZiA9PSAnZnVuY3Rpb24nID8gdmFsdWUudmFsdWVPZigpIDogdmFsdWU7XG4gICAgdmFsdWUgPSBpc09iamVjdChvdGhlcikgPyAob3RoZXIgKyAnJykgOiBvdGhlcjtcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiArdmFsdWU7XG4gIH1cbiAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICB2YXIgaXNCaW5hcnkgPSByZUlzQmluYXJ5LnRlc3QodmFsdWUpO1xuICByZXR1cm4gKGlzQmluYXJ5IHx8IHJlSXNPY3RhbC50ZXN0KHZhbHVlKSlcbiAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICA6IChyZUlzQmFkSGV4LnRlc3QodmFsdWUpID8gTkFOIDogK3ZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0aHJvdHRsZTtcbiIsInZhciBnO1xyXG5cclxuLy8gVGhpcyB3b3JrcyBpbiBub24tc3RyaWN0IG1vZGVcclxuZyA9IChmdW5jdGlvbigpIHtcclxuXHRyZXR1cm4gdGhpcztcclxufSkoKTtcclxuXHJcbnRyeSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiBldmFsIGlzIGFsbG93ZWQgKHNlZSBDU1ApXHJcblx0ZyA9IGcgfHwgRnVuY3Rpb24oXCJyZXR1cm4gdGhpc1wiKSgpIHx8ICgxLCBldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2ggKGUpIHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIHRoZSB3aW5kb3cgcmVmZXJlbmNlIGlzIGF2YWlsYWJsZVxyXG5cdGlmICh0eXBlb2Ygd2luZG93ID09PSBcIm9iamVjdFwiKSBnID0gd2luZG93O1xyXG59XHJcblxyXG4vLyBnIGNhbiBzdGlsbCBiZSB1bmRlZmluZWQsIGJ1dCBub3RoaW5nIHRvIGRvIGFib3V0IGl0Li4uXHJcbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXHJcbi8vIGVhc2llciB0byBoYW5kbGUgdGhpcyBjYXNlLiBpZighZ2xvYmFsKSB7IC4uLn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZztcclxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmNvbnN0IHNjcm9sbF9zeW5jXzEgPSByZXF1aXJlKFwiLi9zY3JvbGwtc3luY1wiKTtcbmNsYXNzIEFjdGl2ZUxpbmVNYXJrZXIge1xuICAgIG9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihsaW5lKSB7XG4gICAgICAgIGNvbnN0IHsgcHJldmlvdXMgfSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKGxpbmUpO1xuICAgICAgICB0aGlzLl91cGRhdGUocHJldmlvdXMgJiYgcHJldmlvdXMuZWxlbWVudCk7XG4gICAgfVxuICAgIF91cGRhdGUoYmVmb3JlKSB7XG4gICAgICAgIHRoaXMuX3VubWFya0FjdGl2ZUVsZW1lbnQodGhpcy5fY3VycmVudCk7XG4gICAgICAgIHRoaXMuX21hcmtBY3RpdmVFbGVtZW50KGJlZm9yZSk7XG4gICAgICAgIHRoaXMuX2N1cnJlbnQgPSBiZWZvcmU7XG4gICAgfVxuICAgIF91bm1hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50LmNsYXNzTmFtZS5yZXBsYWNlKC9cXGJjb2RlLWFjdGl2ZS1saW5lXFxiL2csICcnKTtcbiAgICB9XG4gICAgX21hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgKz0gJyBjb2RlLWFjdGl2ZS1saW5lJztcbiAgICB9XG59XG5leHBvcnRzLkFjdGl2ZUxpbmVNYXJrZXIgPSBBY3RpdmVMaW5lTWFya2VyO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmZ1bmN0aW9uIG9uY2VEb2N1bWVudExvYWRlZChmKSB7XG4gICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGYpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZigpO1xuICAgIH1cbn1cbmV4cG9ydHMub25jZURvY3VtZW50TG9hZGVkID0gb25jZURvY3VtZW50TG9hZGVkO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGFjdGl2ZUxpbmVNYXJrZXJfMSA9IHJlcXVpcmUoXCIuL2FjdGl2ZUxpbmVNYXJrZXJcIik7XG5jb25zdCBldmVudHNfMSA9IHJlcXVpcmUoXCIuL2V2ZW50c1wiKTtcbmNvbnN0IG1lc3NhZ2luZ18xID0gcmVxdWlyZShcIi4vbWVzc2FnaW5nXCIpO1xuY29uc3Qgc2Nyb2xsX3N5bmNfMSA9IHJlcXVpcmUoXCIuL3Njcm9sbC1zeW5jXCIpO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuY29uc3QgdGhyb3R0bGUgPSByZXF1aXJlKFwibG9kYXNoLnRocm90dGxlXCIpO1xubGV0IHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbmNvbnN0IG1hcmtlciA9IG5ldyBhY3RpdmVMaW5lTWFya2VyXzEuQWN0aXZlTGluZU1hcmtlcigpO1xuY29uc3Qgc2V0dGluZ3MgPSBzZXR0aW5nc18xLmdldFNldHRpbmdzKCk7XG5jb25zdCB2c2NvZGUgPSBhY3F1aXJlVnNDb2RlQXBpKCk7XG4vLyBTZXQgVlMgQ29kZSBzdGF0ZVxubGV0IHN0YXRlID0gc2V0dGluZ3NfMS5nZXREYXRhKCdkYXRhLXN0YXRlJyk7XG52c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuY29uc3QgbWVzc2FnaW5nID0gbWVzc2FnaW5nXzEuY3JlYXRlUG9zdGVyRm9yVnNDb2RlKHZzY29kZSk7XG53aW5kb3cuY3NwQWxlcnRlci5zZXRQb3N0ZXIobWVzc2FnaW5nKTtcbndpbmRvdy5zdHlsZUxvYWRpbmdNb25pdG9yLnNldFBvc3RlcihtZXNzYWdpbmcpO1xud2luZG93Lm9ubG9hZCA9ICgpID0+IHtcbiAgICB1cGRhdGVJbWFnZVNpemVzKCk7XG59O1xuZXZlbnRzXzEub25jZURvY3VtZW50TG9hZGVkKCgpID0+IHtcbiAgICBpZiAoc2V0dGluZ3Muc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAvLyBUcnkgdG8gc2Nyb2xsIHRvIGZyYWdtZW50IGlmIGF2YWlsYWJsZVxuICAgICAgICAgICAgaWYgKHN0YXRlLmZyYWdtZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHNjcm9sbF9zeW5jXzEuZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudChzdGF0ZS5mcmFnbWVudCk7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShlbGVtZW50LmxpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluaXRpYWxMaW5lID0gK3NldHRpbmdzLmxpbmU7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihpbml0aWFsTGluZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShpbml0aWFsTGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICB9XG59KTtcbmNvbnN0IG9uVXBkYXRlVmlldyA9ICgoKSA9PiB7XG4gICAgY29uc3QgZG9TY3JvbGwgPSB0aHJvdHRsZSgobGluZSkgPT4ge1xuICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGxpbmUpO1xuICAgIH0sIDUwKTtcbiAgICByZXR1cm4gKGxpbmUsIHNldHRpbmdzKSA9PiB7XG4gICAgICAgIGlmICghaXNOYU4obGluZSkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmxpbmUgPSBsaW5lO1xuICAgICAgICAgICAgZG9TY3JvbGwobGluZSk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcbmxldCB1cGRhdGVJbWFnZVNpemVzID0gdGhyb3R0bGUoKCkgPT4ge1xuICAgIGNvbnN0IGltYWdlSW5mbyA9IFtdO1xuICAgIGxldCBpbWFnZXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaW1nJyk7XG4gICAgaWYgKGltYWdlcykge1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGltYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgaW1nID0gaW1hZ2VzW2ldO1xuICAgICAgICAgICAgaWYgKGltZy5jbGFzc0xpc3QuY29udGFpbnMoJ2xvYWRpbmcnKSkge1xuICAgICAgICAgICAgICAgIGltZy5jbGFzc0xpc3QucmVtb3ZlKCdsb2FkaW5nJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbWFnZUluZm8ucHVzaCh7XG4gICAgICAgICAgICAgICAgaWQ6IGltZy5pZCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGltZy5oZWlnaHQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGltZy53aWR0aFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjYWNoZUltYWdlU2l6ZXMnLCBpbWFnZUluZm8pO1xuICAgIH1cbn0sIDUwKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCAoKSA9PiB7XG4gICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgIHVwZGF0ZUltYWdlU2l6ZXMoKTtcbn0sIHRydWUpO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBldmVudCA9PiB7XG4gICAgaWYgKGV2ZW50LmRhdGEuc291cmNlICE9PSBzZXR0aW5ncy5zb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzd2l0Y2ggKGV2ZW50LmRhdGEudHlwZSkge1xuICAgICAgICBjYXNlICdvbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24nOlxuICAgICAgICAgICAgbWFya2VyLm9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihldmVudC5kYXRhLmxpbmUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3VwZGF0ZVZpZXcnOlxuICAgICAgICAgICAgb25VcGRhdGVWaWV3KGV2ZW50LmRhdGEubGluZSwgc2V0dGluZ3MpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufSwgZmFsc2UpO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBldmVudCA9PiB7XG4gICAgaWYgKCFzZXR0aW5ncy5kb3VibGVDbGlja1RvU3dpdGNoVG9FZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBJZ25vcmUgY2xpY2tzIG9uIGxpbmtzXG4gICAgZm9yIChsZXQgbm9kZSA9IGV2ZW50LnRhcmdldDsgbm9kZTsgbm9kZSA9IG5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICBpZiAobm9kZS50YWdOYW1lID09PSAnQScpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBvZmZzZXQgPSBldmVudC5wYWdlWTtcbiAgICBjb25zdCBsaW5lID0gc2Nyb2xsX3N5bmNfMS5nZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldChvZmZzZXQpO1xuICAgIGlmICh0eXBlb2YgbGluZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnZGlkQ2xpY2snLCB7IGxpbmU6IE1hdGguZmxvb3IobGluZSkgfSk7XG4gICAgfVxufSk7XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGV2ZW50ID0+IHtcbiAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IG5vZGUgPSBldmVudC50YXJnZXQ7XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUudGFnTmFtZSAmJiBub2RlLnRhZ05hbWUgPT09ICdBJyAmJiBub2RlLmhyZWYpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUuaHJlZi5zdGFydHNXaXRoKCdmaWxlOi8vJykgfHwgbm9kZS5ocmVmLnN0YXJ0c1dpdGgoJ3ZzY29kZS1yZXNvdXJjZTonKSB8fCBub2RlLmhyZWYuc3RhcnRzV2l0aChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtwYXRoLCBmcmFnbWVudF0gPSBub2RlLmhyZWZcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL15maWxlOlxcL1xcLy9pLCAnJylcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL152c2NvZGUtcmVzb3VyY2U6XFwvXFwvW15cXC9dK1xcLy9pLCAnJylcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UobmV3IFJlZ0V4cChgXiR7ZXNjYXBlUmVnRXhwKHNldHRpbmdzLndlYnZpZXdSZXNvdXJjZVJvb3QpfWApKVxuICAgICAgICAgICAgICAgICAgICAuc3BsaXQoJyMnKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NsaWNrTGluaycsIHsgcGF0aCwgZnJhZ21lbnQgfSk7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgfVxufSwgdHJ1ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhyb3R0bGUoKCkgPT4ge1xuICAgIGlmIChzY3JvbGxEaXNhYmxlZCkge1xuICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuICAgICAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdyZXZlYWxMaW5lJywgeyBsaW5lIH0pO1xuICAgICAgICAgICAgc3RhdGUubGluZSA9IGxpbmU7XG4gICAgICAgICAgICB2c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxufSwgNTApKTtcbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKTtcbn1cbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5leHBvcnRzLmNyZWF0ZVBvc3RlckZvclZzQ29kZSA9ICh2c2NvZGUpID0+IHtcbiAgICByZXR1cm4gbmV3IGNsYXNzIHtcbiAgICAgICAgcG9zdE1lc3NhZ2UodHlwZSwgYm9keSkge1xuICAgICAgICAgICAgdnNjb2RlLnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgIHNvdXJjZTogc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNvdXJjZSxcbiAgICAgICAgICAgICAgICBib2R5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmZ1bmN0aW9uIGNsYW1wKG1pbiwgbWF4LCB2YWx1ZSkge1xuICAgIHJldHVybiBNYXRoLm1pbihtYXgsIE1hdGgubWF4KG1pbiwgdmFsdWUpKTtcbn1cbmZ1bmN0aW9uIGNsYW1wTGluZShsaW5lKSB7XG4gICAgcmV0dXJuIGNsYW1wKDAsIHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKS5saW5lQ291bnQgLSAxLCBsaW5lKTtcbn1cbmNvbnN0IGdldENvZGVMaW5lRWxlbWVudHMgPSAoKCkgPT4ge1xuICAgIGxldCBlbGVtZW50cztcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAoIWVsZW1lbnRzKSB7XG4gICAgICAgICAgICBlbGVtZW50cyA9IFt7IGVsZW1lbnQ6IGRvY3VtZW50LmJvZHksIGxpbmU6IDAgfV07XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS1saW5lJykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsaW5lID0gK2VsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWxpbmUnKTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzLnB1c2goeyBlbGVtZW50OiBlbGVtZW50LCBsaW5lIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgfTtcbn0pKCk7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBtYXAgdG8gYSBzcGVjaWZpYyB0YXJnZXQgbGluZSBpbiB0aGUgZWRpdG9yLlxuICpcbiAqIElmIGFuIGV4YWN0IG1hdGNoLCByZXR1cm5zIGEgc2luZ2xlIGVsZW1lbnQuIElmIHRoZSBsaW5lIGlzIGJldHdlZW4gZWxlbWVudHMsXG4gKiByZXR1cm5zIHRoZSBlbGVtZW50IHByaW9yIHRvIGFuZCB0aGUgZWxlbWVudCBhZnRlciB0aGUgZ2l2ZW4gbGluZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKHRhcmdldExpbmUpIHtcbiAgICBjb25zdCBsaW5lTnVtYmVyID0gTWF0aC5mbG9vcih0YXJnZXRMaW5lKTtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBsZXQgcHJldmlvdXMgPSBsaW5lc1swXSB8fCBudWxsO1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgbGluZXMpIHtcbiAgICAgICAgaWYgKGVudHJ5LmxpbmUgPT09IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzOiBlbnRyeSwgbmV4dDogdW5kZWZpbmVkIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZW50cnkubGluZSA+IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzLCBuZXh0OiBlbnRyeSB9O1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzID0gZW50cnk7XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzIH07XG59XG5leHBvcnRzLmdldEVsZW1lbnRzRm9yU291cmNlTGluZSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZTtcbi8qKlxuICogRmluZCB0aGUgaHRtbCBlbGVtZW50cyB0aGF0IGFyZSBhdCBhIHNwZWNpZmljIHBpeGVsIG9mZnNldCBvbiB0aGUgcGFnZS5cbiAqL1xuZnVuY3Rpb24gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IGxpbmVzID0gZ2V0Q29kZUxpbmVFbGVtZW50cygpO1xuICAgIGNvbnN0IHBvc2l0aW9uID0gb2Zmc2V0IC0gd2luZG93LnNjcm9sbFk7XG4gICAgbGV0IGxvID0gLTE7XG4gICAgbGV0IGhpID0gbGluZXMubGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAobG8gKyAxIDwgaGkpIHtcbiAgICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG8gKyBoaSkgLyAyKTtcbiAgICAgICAgY29uc3QgYm91bmRzID0gbGluZXNbbWlkXS5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBpZiAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgPj0gcG9zaXRpb24pIHtcbiAgICAgICAgICAgIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG8gPSBtaWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaGlFbGVtZW50ID0gbGluZXNbaGldO1xuICAgIGNvbnN0IGhpQm91bmRzID0gaGlFbGVtZW50LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgaWYgKGhpID49IDEgJiYgaGlCb3VuZHMudG9wID4gcG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgbG9FbGVtZW50ID0gbGluZXNbbG9dO1xuICAgICAgICByZXR1cm4geyBwcmV2aW91czogbG9FbGVtZW50LCBuZXh0OiBoaUVsZW1lbnQgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcHJldmlvdXM6IGhpRWxlbWVudCB9O1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQgPSBnZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQ7XG4vKipcbiAqIEF0dGVtcHQgdG8gcmV2ZWFsIHRoZSBlbGVtZW50IGZvciBhIHNvdXJjZSBsaW5lIGluIHRoZSBlZGl0b3IuXG4gKi9cbmZ1bmN0aW9uIHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKSB7XG4gICAgaWYgKCFzZXR0aW5nc18xLmdldFNldHRpbmdzKCkuc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobGluZSA8PSAwKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcbiAgICBpZiAoIXByZXZpb3VzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHNjcm9sbFRvID0gMDtcbiAgICBjb25zdCByZWN0ID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBwcmV2aW91c1RvcCA9IHJlY3QudG9wO1xuICAgIGlmIChuZXh0ICYmIG5leHQubGluZSAhPT0gcHJldmlvdXMubGluZSkge1xuICAgICAgICAvLyBCZXR3ZWVuIHR3byBlbGVtZW50cy4gR28gdG8gcGVyY2VudGFnZSBvZmZzZXQgYmV0d2VlbiB0aGVtLlxuICAgICAgICBjb25zdCBiZXR3ZWVuUHJvZ3Jlc3MgPSAobGluZSAtIHByZXZpb3VzLmxpbmUpIC8gKG5leHQubGluZSAtIHByZXZpb3VzLmxpbmUpO1xuICAgICAgICBjb25zdCBlbGVtZW50T2Zmc2V0ID0gbmV4dC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtIHByZXZpb3VzVG9wO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgYmV0d2VlblByb2dyZXNzICogZWxlbWVudE9mZnNldDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IHByb2dyZXNzSW5FbGVtZW50ID0gbGluZSAtIE1hdGguZmxvb3IobGluZSk7XG4gICAgICAgIHNjcm9sbFRvID0gcHJldmlvdXNUb3AgKyAocmVjdC5oZWlnaHQgKiBwcm9ncmVzc0luRWxlbWVudCk7XG4gICAgfVxuICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIE1hdGgubWF4KDEsIHdpbmRvdy5zY3JvbGxZICsgc2Nyb2xsVG8pKTtcbn1cbmV4cG9ydHMuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lID0gc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lO1xuZnVuY3Rpb24gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KSB7XG4gICAgY29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCk7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzQm91bmRzID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0RnJvbVByZXZpb3VzID0gKG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgaWYgKG5leHQpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb2dyZXNzQmV0d2VlbkVsZW1lbnRzID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c0JvdW5kcy50b3ApO1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IHByZXZpb3VzLmxpbmUgKyBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyAqIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc1dpdGhpbkVsZW1lbnQgPSBvZmZzZXRGcm9tUHJldmlvdXMgLyAocHJldmlvdXNCb3VuZHMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50O1xuICAgICAgICAgICAgcmV0dXJuIGNsYW1wTGluZShsaW5lKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmV4cG9ydHMuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQgPSBnZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldDtcbi8qKlxuICogVHJ5IHRvIGZpbmQgdGhlIGh0bWwgZWxlbWVudCBieSB1c2luZyBhIGZyYWdtZW50IGlkXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQoZnJhZ21lbnQpIHtcbiAgICByZXR1cm4gZ2V0Q29kZUxpbmVFbGVtZW50cygpLmZpbmQoKGVsZW1lbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuZWxlbWVudC5pZCA9PT0gZnJhZ21lbnQ7XG4gICAgfSk7XG59XG5leHBvcnRzLmdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQgPSBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxldCBjYWNoZWRTZXR0aW5ncyA9IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGdldERhdGEoa2V5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbmZ1bmN0aW9uIGdldFNldHRpbmdzKCkge1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U2V0dGluZ3MgPSBnZXRTZXR0aW5ncztcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/extensions/markdown-language-features/preview-src/index.ts b/extensions/markdown-language-features/preview-src/index.ts index dcf46940aea..aff7254ea79 100644 --- a/extensions/markdown-language-features/preview-src/index.ts +++ b/extensions/markdown-language-features/preview-src/index.ts @@ -157,20 +157,18 @@ document.addEventListener('click', event => { } }, true); -if (settings.scrollEditorWithPreview) { - window.addEventListener('scroll', throttle(() => { - if (scrollDisabled) { - scrollDisabled = false; - } else { - const line = getEditorLineNumberForPageOffset(window.scrollY); - if (typeof line === 'number' && !isNaN(line)) { - messaging.postMessage('revealLine', { line }); - state.line = line; - vscode.setState(state); - } +window.addEventListener('scroll', throttle(() => { + if (scrollDisabled) { + scrollDisabled = false; + } else { + const line = getEditorLineNumberForPageOffset(window.scrollY); + if (typeof line === 'number' && !isNaN(line)) { + messaging.postMessage('revealLine', { line }); + state.line = line; + vscode.setState(state); } - }, 50)); -} + } +}, 50)); function escapeRegExp(text: string) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index 00224e1364d..b1cbe39e5af 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -284,15 +284,17 @@ export class MarkdownPreview extends Disposable { super.dispose(); } - public update(resource: vscode.Uri) { - const editor = vscode.window.activeTextEditor; + public update(resource: vscode.Uri, isRefresh = true) { // Reposition scroll preview, position scroll to the top if active text editor // doesn't corresponds with preview + const editor = vscode.window.activeTextEditor; if (editor) { - if (editor.document.uri.fsPath === resource.fsPath) { - this.line = getVisibleLine(editor); - } else { - this.line = 0; + if (!isRefresh || this._previewConfigurations.loadAndCacheConfiguration(this._resource).scrollEditorWithPreview) { + if (editor.document.uri.fsPath === resource.fsPath) { + this.line = getVisibleLine(editor); + } else { + this.line = 0; + } } } @@ -320,7 +322,7 @@ export class MarkdownPreview extends Disposable { public refresh() { this.forceUpdate = true; - this.update(this._resource); + this.update(this._resource, true); } public updateConfiguration() { @@ -484,6 +486,12 @@ export class MarkdownPreview extends Disposable { private onDidScrollPreview(line: number) { this.line = line; + + const config = this._previewConfigurations.loadAndCacheConfiguration(this._resource); + if (!config.scrollEditorWithPreview) { + return; + } + for (const editor of vscode.window.visibleTextEditors) { if (!this.isPreviewOf(editor.document.uri)) { continue; From bac36e97c68a13488088db60c28410e7321d2871 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Oct 2019 13:33:43 -0700 Subject: [PATCH 155/435] Close image preview when file on disk is deleted Fixes #81884 --- extensions/image-preview/src/preview.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 89e60097942..2d5963adc1b 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -88,6 +88,11 @@ export class Preview extends Disposable { this.render(); } })); + this._register(watcher.onDidDelete(e => { + if (e.toString() === this.resource.toString()) { + this.webviewEditor.dispose(); + } + })); this.render(); this.update(); From eacd477ea9a7b4d72cc0bdfac0c7898cfde645eb Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Oct 2019 13:46:19 -0700 Subject: [PATCH 156/435] Only reuse existing custom editor input if we are opening an editor in the same group --- .../customEditor/browser/customEditors.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 438566bb925..0edbf4912e0 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -160,7 +160,7 @@ export class CustomEditorService implements ICustomEditorService { const webview = this.webviewService.createWebviewEditorOverlay(id, { customClasses: options ? options.customClasses : undefined }, {}); const input = this.instantiationService.createInstance(CustomFileEditorInput, resource, viewType, id, new UnownedDisposable(webview)); if (group) { - input.updateGroup(group!.id); + input.updateGroup(group.id); } return input; } @@ -175,18 +175,16 @@ export class CustomEditorService implements ICustomEditorService { const existingEditors = group.editors.filter(editor => editor.getResource() && isEqual(editor.getResource()!, resource)); if (existingEditors.length) { const existing = existingEditors[0]; - if (input.matches(existing)) { - return; - } + if (!input.matches(existing)) { + await this.editorService.replaceEditors([{ + editor: existing, + replacement: input, + options: options ? EditorOptions.create(options) : undefined, + }], group); - await this.editorService.replaceEditors([{ - editor: existing, - replacement: input, - options: options ? EditorOptions.create(options) : undefined, - }], group); - - if (existing instanceof CustomFileEditorInput) { - existing.dispose(); + if (existing instanceof CustomFileEditorInput) { + existing.dispose(); + } } } } @@ -212,7 +210,9 @@ export class CustomEditorContribution implements IWorkbenchContribution { group: IEditorGroup ): IOpenEditorOverride | undefined { if (editor instanceof CustomFileEditorInput) { - return undefined; + if (editor.group === group.id) { + return undefined; + } } if (editor instanceof DiffEditorInput) { From d3eb24828e2d977e4f3ac16ff1a332a020028464 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 3 Oct 2019 13:53:30 -0700 Subject: [PATCH 157/435] Use strict compare for checking if an editor is active/visible Fixes #81889 Using `.matches` can cause a custom editor to match all custom editors for that resource. Use a strict compare instead. --- src/vs/workbench/api/browser/mainThreadWebview.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index c5e3d474583..9f2da86e2bf 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -340,8 +340,8 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews const handle = this._webviewEditorInputs.getHandleForInput(editorInput); if (handle) { viewStates[handle] = { - visible: topLevelInput.matches(group.activeEditor), - active: topLevelInput.matches(activeInput), + visible: topLevelInput === group.activeEditor, + active: topLevelInput === activeInput, position: editorGroupToViewColumn(this._editorGroupService, group.id), }; } From c836d5ae3801c2c59e0f1f7e46e13e05fa606692 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 3 Oct 2019 14:04:51 -0700 Subject: [PATCH 158/435] Include icons in the extension viewlet --- src/vs/platform/severityIcon/common/severityIcon.ts | 6 ++++-- .../workbench/contrib/extensions/browser/extensionsViews.ts | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/severityIcon/common/severityIcon.ts b/src/vs/platform/severityIcon/common/severityIcon.ts index b415e5d8786..946313a389e 100644 --- a/src/vs/platform/severityIcon/common/severityIcon.ts +++ b/src/vs/platform/severityIcon/common/severityIcon.ts @@ -30,7 +30,8 @@ registerThemingParticipant((theme, collector) => { if (errorIconForeground) { collector.addRule(` .monaco-workbench .zone-widget .codicon-error, - .monaco-workbench .markers-panel .marker-icon.codicon-error { + .monaco-workbench .markers-panel .marker-icon.codicon-error, + .monaco-workbench .extensions-viewlet > .extensions .codicon-error { color: ${errorIconForeground}; } `); @@ -40,7 +41,8 @@ registerThemingParticipant((theme, collector) => { if (errorIconForeground) { collector.addRule(` .monaco-workbench .zone-widget .codicon-warning, - .monaco-workbench .markers-panel .marker-icon.codicon-warning { + .monaco-workbench .markers-panel .marker-icon.codicon-warning, + .monaco-workbench .extensions-viewlet > .extensions .codicon-warning { color: ${warningIconForeground}; } `); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index 9230ee1708c..ba71b25d71a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -708,10 +708,10 @@ export class ExtensionsListView extends ViewletPanel { if (count === 0 && this.isBodyVisible()) { if (error) { if (error instanceof ExtensionListViewWarning) { - this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Warning); + this.bodyTemplate.messageSeverityIcon.className = 'codicon ' + SeverityIcon.className(Severity.Warning); this.bodyTemplate.messageBox.textContent = getErrorMessage(error); } else { - this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Error); + this.bodyTemplate.messageSeverityIcon.className = 'codicon ' + SeverityIcon.className(Severity.Error); this.bodyTemplate.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error)); } } else { From c8252b63f547674d2faf361d4181bb76b0b5f81a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 4 Oct 2019 10:43:55 +0200 Subject: [PATCH 159/435] Revert "fixes #80054" (#81942) This reverts commit d591cb7e6d4e986ac177bc4465b8c70f481b5a98. --- .../extensions/browser/extensionUrlHandler.ts | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 62d36c968e1..6a9a536c7a6 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -28,6 +28,7 @@ const FIVE_MINUTES = 5 * 60 * 1000; const THIRTY_SECONDS = 30 * 1000; const URL_TO_HANDLE = 'extensionUrlHandler.urlToHandle'; const CONFIRMED_EXTENSIONS_CONFIGURATION_KEY = 'extensions.confirmedUriHandlerExtensionIds'; +const CONFIRMED_EXTENSIONS_STORAGE_KEY = 'extensionUrlHandler.confirmedExtensions'; function isExtensionId(value: string): boolean { return /^[a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*$/i.test(value); @@ -130,7 +131,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { } if (result.checkboxChecked) { - await this.addConfirmedExtensionIdToStorage(extensionId); + this.addConfirmedExtensionIdToStorage(extensionId); } } @@ -292,8 +293,10 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { } private getConfirmedExtensionIds(): Set { - const ids = this.getConfirmedExtensionIdsFromConfiguration() - .map(extensionId => ExtensionIdentifier.toKey(extensionId)); + const ids = [ + ...this.getConfirmedExtensionIdsFromStorage(), + ...this.getConfirmedExtensionIdsFromConfiguration(), + ].map(extensionId => ExtensionIdentifier.toKey(extensionId)); return new Set(ids); } @@ -308,12 +311,26 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { return confirmedExtensionIds; } - private async addConfirmedExtensionIdToStorage(extensionId: string): Promise { - const confirmedExtensionIds = this.configurationService.getValue>(CONFIRMED_EXTENSIONS_CONFIGURATION_KEY); - const set = new Set(confirmedExtensionIds); - set.add(extensionId); + private getConfirmedExtensionIdsFromStorage(): Array { + const confirmedExtensionIdsJson = this.storageService.get(CONFIRMED_EXTENSIONS_STORAGE_KEY, StorageScope.GLOBAL, '[]'); - await this.configurationService.updateValue(CONFIRMED_EXTENSIONS_CONFIGURATION_KEY, [...set.values()]); + try { + return JSON.parse(confirmedExtensionIdsJson); + } catch (err) { + return []; + } + } + + private addConfirmedExtensionIdToStorage(extensionId: string): void { + const existingConfirmedExtensionIds = this.getConfirmedExtensionIdsFromStorage(); + this.storageService.store( + CONFIRMED_EXTENSIONS_STORAGE_KEY, + JSON.stringify([ + ...existingConfirmedExtensionIds, + ExtensionIdentifier.toKey(extensionId), + ]), + StorageScope.GLOBAL, + ); } dispose(): void { From c06c223ee99c18c81b1040ef6ade618daa29969d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Oct 2019 11:52:05 +0200 Subject: [PATCH 160/435] more strict init work --- .../ui/highlightedlabel/highlightedLabel.ts | 10 ++++---- .../api/browser/mainThreadStatusBar.ts | 6 ++++- .../workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostStatusBar.ts | 24 +++++++++---------- .../api/extHostConfiguration.test.ts | 2 +- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index e7dcf431b0d..cd2e4b3703d 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -15,15 +15,15 @@ export interface IHighlight { export class HighlightedLabel { private domNode: HTMLElement; - private text: string; - private title: string; - private highlights: IHighlight[]; - private didEverRender: boolean; + private text: string = ''; + private title: string = ''; + private highlights: IHighlight[] = []; + private didEverRender: boolean = false; constructor(container: HTMLElement, private supportOcticons: boolean) { this.domNode = document.createElement('span'); this.domNode.className = 'monaco-highlighted-label'; - this.didEverRender = false; + container.appendChild(this.domNode); } diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 611538d554f..91a9ba1419f 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -24,9 +24,13 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this.entries.clear(); } - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void { + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: string | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined): void { const entry: IStatusbarEntry = { text, tooltip, command, color }; + if (typeof priority === 'undefined') { + priority = 0; + } + // Reset existing entry if alignment or priority changed let existingEntry = this.entries.get(id); if (existingEntry && (existingEntry.alignment !== alignment || existingEntry.priority !== priority)) { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7bd6aa6cb78..6400262b603 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -505,7 +505,7 @@ export interface MainThreadQuickOpenShape extends IDisposable { } export interface MainThreadStatusBarShape extends IDisposable { - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void; + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: string | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void; $dispose(id: number): void; } diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index d744fdd80d2..02c89a6e89e 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -15,16 +15,16 @@ export class ExtHostStatusBarEntry implements StatusBarItem { private _id: number; private _alignment: number; private _priority?: number; - private _disposed: boolean; - private _visible: boolean; + private _disposed: boolean = false; + private _visible: boolean = false; private _statusId: string; private _statusName: string; - private _text: string; - private _tooltip: string; - private _color: string | ThemeColor; - private _command: string; + private _text: string = ''; + private _tooltip?: string; + private _color?: string | ThemeColor; + private _command?: string; private _timeoutHandle: any; private _proxy: MainThreadStatusBarShape; @@ -54,15 +54,15 @@ export class ExtHostStatusBarEntry implements StatusBarItem { return this._text; } - public get tooltip(): string { + public get tooltip(): string | undefined { return this._tooltip; } - public get color(): string | ThemeColor { + public get color(): string | ThemeColor | undefined { return this._color; } - public get command(): string { + public get command(): string | undefined { return this._command; } @@ -71,17 +71,17 @@ export class ExtHostStatusBarEntry implements StatusBarItem { this.update(); } - public set tooltip(tooltip: string) { + public set tooltip(tooltip: string | undefined) { this._tooltip = tooltip; this.update(); } - public set color(color: string | ThemeColor) { + public set color(color: string | ThemeColor | undefined) { this._color = color; this.update(); } - public set command(command: string) { + public set command(command: string | undefined) { this._command = command; this.update(); } 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 c2bfcdd6605..f319881a103 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -20,7 +20,7 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData suite('ExtHostConfiguration', function () { class RecordingShape extends mock() { - lastArgs: [ConfigurationTarget, string, any]; + lastArgs!: [ConfigurationTarget, string, any]; $updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): Promise { this.lastArgs = [target, key, value]; return Promise.resolve(undefined); From c310c24e58540351862edd9e2926c8ced5d4c52f Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Fri, 4 Oct 2019 13:07:03 +0200 Subject: [PATCH 161/435] Allow labels being triggered by the bot --- .github/commands.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/commands.yml b/.github/commands.yml index 4bc649c91b6..6344ec67692 100644 --- a/.github/commands.yml +++ b/.github/commands.yml @@ -18,24 +18,28 @@ { type: 'label', name: '*dev-question', + allowTriggerByBot: true, action: 'close', comment: "We have a great developer community [over on slack](https://aka.ms/vscode-dev-community) where extension authors help each other. This is a great place for you to ask questions and find support.\n\nHappy Coding!" }, { type: 'label', name: '*extension-candidate', + allowTriggerByBot: true, action: 'close', comment: "We try to keep VS Code lean and we think the functionality you're asking for is great for a VS Code extension. Maybe you can already find one that suits you in the [VS Code Marketplace](https://aka.ms/vscodemarketplace). Just in case, in a few simple steps you can get started [writing your own extension](https://aka.ms/vscodewritingextensions). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" }, { type: 'label', name: '*not-reproducible', + allowTriggerByBot: true, action: 'close', comment: "We closed this issue because we are unable to reproduce the problem with the steps you describe. Chances are we've already fixed your problem in a recent version of VS Code. If not, please ask us to reopen the issue and provide us with more detail. Our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines might help you with that.\n\nHappy Coding!" }, { type: 'label', name: '*out-of-scope', + allowTriggerByBot: true, action: 'close', comment: "This issue is being closed to keep the number of issues in our inbox on a manageable level, we are closing issues that are not going to be addressed in the foreseeable future: We look at the number of votes the issue has received and the number of duplicate issues filed. More details [here](https://aka.ms/vscode-out-of-scope). If you disagree and feel that this issue is crucial: We are happy to listen and to reconsider.\n\nIf you wonder what we are up to, please see our [roadmap](https://aka.ms/vscoderoadmap) and [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nThanks for your understanding and happy coding!" }, @@ -56,12 +60,14 @@ { type: 'label', name: '*as-designed', + allowTriggerByBot: true, action: 'close', comment: "The described behavior is how it is expected to work. If you disagree, please explain what is expected and what is not in more detail. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" }, { type: 'label', name: '*english-please', + allowTriggerByBot: true, action: 'close', comment: "This issue is being closed because its description is not in English, that makes it hard for us to work on it. Please open a new issue with an English description. You might find [Bing Translator](https://www.bing.com/translator) useful." }, From 94c9c09627027569369b030e9d3c0d67c69fae83 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 4 Oct 2019 09:20:09 -0700 Subject: [PATCH 162/435] Update syntax --- src/vs/editor/contrib/gotoError/gotoErrorWidget.ts | 2 +- .../workbench/contrib/extensions/browser/extensionsViews.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts index c6a10084db3..a8aa26cb3a9 100644 --- a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -283,7 +283,7 @@ export class MarkerNavigationWidget extends PeekViewWidget { : nls.localize('change', "{0} of {1} problem", markerIdx, markerCount); this.setTitle(basename(model.uri), detail); } - this._icon.className = 'codicon ' + SeverityIcon.className(MarkerSeverity.toSeverity(this._severity)); + this._icon.className = `codicon ${SeverityIcon.className(MarkerSeverity.toSeverity(this._severity))}`; this.editor.revealPositionInCenter(position, ScrollType.Smooth); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index ba71b25d71a..bb17633367f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -708,10 +708,10 @@ export class ExtensionsListView extends ViewletPanel { if (count === 0 && this.isBodyVisible()) { if (error) { if (error instanceof ExtensionListViewWarning) { - this.bodyTemplate.messageSeverityIcon.className = 'codicon ' + SeverityIcon.className(Severity.Warning); + this.bodyTemplate.messageSeverityIcon.className = `codicon ${SeverityIcon.className(Severity.Warning)}`; this.bodyTemplate.messageBox.textContent = getErrorMessage(error); } else { - this.bodyTemplate.messageSeverityIcon.className = 'codicon ' + SeverityIcon.className(Severity.Error); + this.bodyTemplate.messageSeverityIcon.className = `codicon ${SeverityIcon.className(Severity.Error)}`; this.bodyTemplate.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error)); } } else { From a46c17e5b977ab2a871204f3c20df805f63a951a Mon Sep 17 00:00:00 2001 From: Keyon You Date: Sat, 5 Oct 2019 03:19:13 +0800 Subject: [PATCH 163/435] Update button.ts Press `space` key on a disabled button should not trig click event --- src/vs/base/browser/ui/button/button.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index a982d959b1c..575122ccd77 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -79,7 +79,7 @@ export class Button extends Disposable { this._register(DOM.addDisposableListener(this._element, DOM.EventType.KEY_DOWN, e => { const event = new StandardKeyboardEvent(e); let eventHandled = false; - if (this.enabled && event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { + if (this.enabled && (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) { this._onDidClick.fire(e); eventHandled = true; } else if (event.equals(KeyCode.Escape)) { From 05de12c548a8a2267a8a18beae0217d62f1bbf99 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:08:46 -0700 Subject: [PATCH 164/435] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc653251cbd..275623fa18b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "code-oss-dev", - "version": "1.39.0", + "version": "1.40.0", "distro": "b9bb6392c20ba05a247e41ea75b2825544fd8afd", "author": { "name": "Microsoft Corporation" From 41a26f032218839ef6e639dc1e24f0bbb4ca841f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:18:07 -0700 Subject: [PATCH 165/435] Fixing some TS 3.7 dom typing errors TS 3.7 changes the many dom style typings to just be `string` instead of `string | null`. Use empty string in place of null for these cases --- src/vs/base/browser/ui/checkbox/checkbox.ts | 4 ++-- .../contrib/colorPicker/colorPickerWidget.ts | 6 +++--- .../workbench/browser/parts/compositeBarActions.ts | 14 +++++++------- .../suggestEnabledInput/suggestEnabledInput.ts | 4 ++-- .../contrib/files/browser/views/openEditorsView.ts | 10 +++++----- .../preferences/browser/preferencesWidgets.ts | 8 ++++---- .../contrib/preferences/browser/settingsEditor2.ts | 10 +++++----- .../welcome/overlay/browser/welcomeOverlay.ts | 4 ++-- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index 6bc9a8e3d4c..e5f64f9174c 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -219,7 +219,7 @@ export class SimpleCheckbox extends Widget { protected applyStyles(): void { this.domNode.style.color = this.styles.checkboxForeground ? this.styles.checkboxForeground.toString() : null; - this.domNode.style.backgroundColor = this.styles.checkboxBackground ? this.styles.checkboxBackground.toString() : null; - this.domNode.style.borderColor = this.styles.checkboxBorder ? this.styles.checkboxBorder.toString() : null; + this.domNode.style.backgroundColor = this.styles.checkboxBackground ? this.styles.checkboxBackground.toString() : ''; + this.domNode.style.borderColor = this.styles.checkboxBorder ? this.styles.checkboxBorder.toString() : ''; } } diff --git a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts index 64329a79ba9..4a74a4a5e0d 100644 --- a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts +++ b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts @@ -32,7 +32,7 @@ export class ColorPickerHeader extends Disposable { this.pickedColorNode = dom.append(this.domNode, $('.picked-color')); const colorBox = dom.append(this.domNode, $('.original-color')); - colorBox.style.backgroundColor = Color.Format.CSS.format(this.model.originalColor); + colorBox.style.backgroundColor = Color.Format.CSS.format(this.model.originalColor) || ''; this.backgroundColor = themeService.getTheme().getColor(editorHoverBackground) || Color.white; this._register(registerThemingParticipant((theme, collector) => { @@ -46,12 +46,12 @@ export class ColorPickerHeader extends Disposable { })); this._register(model.onDidChangeColor(this.onDidChangeColor, this)); this._register(model.onDidChangePresentation(this.onDidChangePresentation, this)); - this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(model.color); + this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(model.color) || ''; dom.toggleClass(this.pickedColorNode, 'light', model.color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : model.color.isLighter()); } private onDidChangeColor(color: Color): void { - this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(color); + this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(color) || ''; dom.toggleClass(this.pickedColorNode, 'light', color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : color.isLighter()); this.onDidChangePresentation(); } diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 33c609eba58..dde3549cd8f 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -156,12 +156,12 @@ export class ActivityActionViewItem extends BaseActionViewItem { if (this.label) { if (this.options.icon) { const foreground = this._action.checked ? colors.activeBackgroundColor || colors.activeForegroundColor : colors.inactiveBackgroundColor || colors.inactiveForegroundColor; - this.label.style.backgroundColor = foreground ? foreground.toString() : null; + this.label.style.backgroundColor = foreground ? foreground.toString() : ''; } else { const foreground = this._action.checked ? colors.activeForegroundColor : colors.inactiveForegroundColor; const borderBottomColor = this._action.checked ? colors.activeBorderBottomColor : null; this.label.style.color = foreground ? foreground.toString() : null; - this.label.style.borderBottomColor = borderBottomColor ? borderBottomColor.toString() : null; + this.label.style.borderBottomColor = borderBottomColor ? borderBottomColor.toString() : ''; } } @@ -172,11 +172,11 @@ export class ActivityActionViewItem extends BaseActionViewItem { const contrastBorderColor = theme.getColor(contrastBorder); this.badgeContent.style.color = badgeForeground ? badgeForeground.toString() : null; - this.badgeContent.style.backgroundColor = badgeBackground ? badgeBackground.toString() : null; + this.badgeContent.style.backgroundColor = badgeBackground ? badgeBackground.toString() : ''; - this.badgeContent.style.borderStyle = contrastBorderColor ? 'solid' : null; - this.badgeContent.style.borderWidth = contrastBorderColor ? '1px' : null; - this.badgeContent.style.borderColor = contrastBorderColor ? contrastBorderColor.toString() : null; + this.badgeContent.style.borderStyle = contrastBorderColor ? 'solid' : ''; + this.badgeContent.style.borderWidth = contrastBorderColor ? '1px' : ''; + this.badgeContent.style.borderColor = contrastBorderColor ? contrastBorderColor.toString() : ''; } } @@ -563,7 +563,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { const theme = this.themeService.getTheme(); const dragBackground = this.options.colors(theme).dragAndDropBackground; - element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : null; + element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : ''; } private showContextMenu(container: HTMLElement): void { diff --git a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts index 2ce7aef85f7..20d1c228439 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts @@ -216,7 +216,7 @@ export class SuggestEnabledInput extends Widget implements IThemable { public style(colors: ISuggestEnabledInputStyles): void { - this.stylingContainer.style.backgroundColor = colors.inputBackground ? colors.inputBackground.toString() : null; + this.stylingContainer.style.backgroundColor = colors.inputBackground ? colors.inputBackground.toString() : ''; this.stylingContainer.style.color = colors.inputForeground ? colors.inputForeground.toString() : null; this.placeholderText.style.color = colors.inputPlaceholderForeground ? colors.inputPlaceholderForeground.toString() : null; @@ -228,7 +228,7 @@ export class SuggestEnabledInput extends Widget implements IThemable { const cursor = this.stylingContainer.getElementsByClassName('cursor')[0] as HTMLDivElement; if (cursor) { - cursor.style.backgroundColor = colors.inputForeground ? colors.inputForeground.toString() : null; + cursor.style.backgroundColor = colors.inputForeground ? colors.inputForeground.toString() : ''; } } diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 95aa5d90a6e..b3955354dc1 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -185,15 +185,15 @@ export class OpenEditorsView extends ViewletPanel { this.dirtyCountElement = dom.append(count, $('.monaco-count-badge')); this._register((attachStylerCallback(this.themeService, { badgeBackground, badgeForeground, contrastBorder }, colors => { - const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; - const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : null; - const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; + const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; + const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : ''; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : ''; this.dirtyCountElement.style.backgroundColor = background; this.dirtyCountElement.style.color = foreground; - this.dirtyCountElement.style.borderWidth = border ? '1px' : null; - this.dirtyCountElement.style.borderStyle = border ? 'solid' : null; + this.dirtyCountElement.style.borderWidth = border ? '1px' : ''; + this.dirtyCountElement.style.borderStyle = border ? 'solid' : ''; this.dirtyCountElement.style.borderColor = border; }))); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index b79486ab07d..89ea848b7f3 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -632,13 +632,13 @@ export class SearchWidget extends Widget { if (this.options.showResultCount) { this.countElement = DOM.append(this.controlsDiv, DOM.$('.settings-count-widget')); this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder }, colors => { - const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; - const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; + const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : ''; this.countElement.style.backgroundColor = background; - this.countElement.style.borderWidth = border ? '1px' : null; - this.countElement.style.borderStyle = border ? 'solid' : null; + this.countElement.style.borderWidth = border ? '1px' : ''; + this.countElement.style.borderStyle = border ? 'solid' : ''; this.countElement.style.borderColor = border; const color = this.themeService.getTheme().getColor(badgeForeground); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index e837a8221b0..58f1c7f4c50 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -400,15 +400,15 @@ export class SettingsEditor2 extends BaseEditor { this.countElement = DOM.append(searchContainer, DOM.$('.settings-count-widget')); this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder, badgeForeground }, colors => { - const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; - const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; - const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : null; + const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : ''; + const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : ''; this.countElement.style.backgroundColor = background; this.countElement.style.color = foreground; - this.countElement.style.borderWidth = border ? '1px' : null; - this.countElement.style.borderStyle = border ? 'solid' : null; + this.countElement.style.borderWidth = border ? '1px' : ''; + this.countElement.style.borderStyle = border ? 'solid' : ''; this.countElement.style.borderColor = border; })); diff --git a/src/vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay.ts b/src/vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay.ts index 0ba17c87166..d6cbde0d99c 100644 --- a/src/vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay.ts +++ b/src/vs/workbench/contrib/welcome/overlay/browser/welcomeOverlay.ts @@ -222,8 +222,8 @@ class WelcomeOverlay extends Disposable { key.style.bottom = bottom + 'px'; key.style.left = left + 'px'; } else { - key.style.bottom = null; - key.style.left = null; + key.style.bottom = ''; + key.style.left = ''; } } From d08130d4d342c998b5e5f94f0290a47a72098f63 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:21:51 -0700 Subject: [PATCH 166/435] Remove some extra not null checks These checks should not be required now that we have strict null checking enabled --- src/vs/base/common/color.ts | 9 --------- src/vs/base/test/common/color.test.ts | 3 +-- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/vs/base/common/color.ts b/src/vs/base/common/color.ts index 97528a4534c..8068e76aadd 100644 --- a/src/vs/base/common/color.ts +++ b/src/vs/base/common/color.ts @@ -507,10 +507,6 @@ export namespace Color { * The default format will use HEX if opaque and RGBA otherwise. */ export function format(color: Color): string | null { - if (!color) { - return null; - } - if (color.isOpaque()) { return Color.Format.CSS.formatHex(color); } @@ -524,11 +520,6 @@ export namespace Color { * @param hex string (#RGB, #RGBA, #RRGGBB or #RRGGBBAA). */ export function parseHex(hex: string): Color | null { - if (!hex) { - // Invalid color - return null; - } - const length = hex.length; if (length === 0) { diff --git a/src/vs/base/test/common/color.test.ts b/src/vs/base/test/common/color.test.ts index 865c158bab5..47d94c1dbf3 100644 --- a/src/vs/base/test/common/color.test.ts +++ b/src/vs/base/test/common/color.test.ts @@ -196,7 +196,6 @@ suite('Color', () => { test('parseHex', () => { // invalid - assert.deepEqual(Color.Format.CSS.parseHex(null!), null); assert.deepEqual(Color.Format.CSS.parseHex(''), null); assert.deepEqual(Color.Format.CSS.parseHex('#'), null); assert.deepEqual(Color.Format.CSS.parseHex('#0102030'), null); @@ -243,4 +242,4 @@ suite('Color', () => { }); }); }); -}); \ No newline at end of file +}); From 7f044c7903d4cccf88ab2934f92a67188a252c0a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:42:04 -0700 Subject: [PATCH 167/435] Memoize webview theme data Fixes #81788 --- .../contrib/webview/browser/webviewElement.ts | 11 +-- .../contrib/webview/browser/webviewService.ts | 17 +++-- .../contrib/webview/common/themeing.ts | 70 +++++++++++-------- .../electron-browser/webviewElement.ts | 13 ++-- .../electron-browser/webviewService.ts | 13 ++-- 5 files changed, 74 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 6b0c7543233..58c3b3b987d 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -12,12 +12,12 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; -import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { loadLocalResource } from 'vs/workbench/contrib/webview/common/resourceLoader'; -import { getWebviewThemeData } from 'vs/workbench/contrib/webview/common/themeing'; +import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; interface WebviewContent { @@ -45,6 +45,7 @@ export class IFrameWebview extends Disposable implements Webview { private readonly id: string, options: WebviewOptions, contentOptions: WebviewContentOptions, + private readonly webviewThemeDataProvider: WebviewThemeDataProvider, @IThemeService themeService: IThemeService, @ITunnelService tunnelService: ITunnelService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @@ -146,7 +147,7 @@ export class IFrameWebview extends Disposable implements Webview { })); }); - this.style(themeService.getTheme()); + this.style(); this._register(themeService.onThemeChange(this.style, this)); } @@ -307,8 +308,8 @@ export class IFrameWebview extends Disposable implements Webview { .catch(err => console.error(err)); } - private style(theme: ITheme): void { - const { styles, activeTheme } = getWebviewThemeData(theme, this._configurationService); + private style(): void { + const { styles, activeTheme } = this.webviewThemeDataProvider.getWebviewThemeData(); this._send('styles', { styles, activeTheme }); } diff --git a/src/vs/workbench/contrib/webview/browser/webviewService.ts b/src/vs/workbench/contrib/webview/browser/webviewService.ts index 21333aca8bc..0b8c5b01c69 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewService.ts @@ -3,25 +3,30 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement'; -import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; -import { DynamicWebviewEditorOverlay } from './dynamicWebviewEditorOverlay'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement'; +import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; +import { DynamicWebviewEditorOverlay } from './dynamicWebviewEditorOverlay'; export class WebviewService implements IWebviewService { _serviceBrand: undefined; + private readonly _webviewThemeDataProvider: WebviewThemeDataProvider; + constructor( @IInstantiationService private readonly _instantiationService: IInstantiationService, - ) { } + ) { + this._instantiationService.createInstance(WebviewThemeDataProvider); + } createWebview( id: string, options: WebviewOptions, contentOptions: WebviewContentOptions ): WebviewElement { - return this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions); + return this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions, this._webviewThemeDataProvider); } createWebviewEditorOverlay( diff --git a/src/vs/workbench/contrib/webview/common/themeing.ts b/src/vs/workbench/contrib/webview/common/themeing.ts index 7c39b7a4bdd..42c6801ebc6 100644 --- a/src/vs/workbench/contrib/webview/common/themeing.ts +++ b/src/vs/workbench/contrib/webview/common/themeing.ts @@ -3,45 +3,59 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { createMemoizer } from 'vs/base/common/decorators'; +import { Disposable } from 'vs/base/common/lifecycle'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import * as colorRegistry from 'vs/platform/theme/common/colorRegistry'; -import { ITheme, LIGHT, DARK } from 'vs/platform/theme/common/themeService'; +import { DARK, ITheme, IThemeService, LIGHT } from 'vs/platform/theme/common/themeService'; interface WebviewThemeData { readonly activeTheme: string; - readonly styles: { readonly [key: string]: string | number }; + readonly styles: { readonly [key: string]: string | number; }; } -export function getWebviewThemeData( - theme: ITheme, - configurationService: IConfigurationService -): WebviewThemeData { - const configuration = configurationService.getValue('editor'); - const editorFontFamily = configuration.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; - const editorFontWeight = configuration.fontWeight || EDITOR_FONT_DEFAULTS.fontWeight; - const editorFontSize = configuration.fontSize || EDITOR_FONT_DEFAULTS.fontSize; +export class WebviewThemeDataProvider extends Disposable { - const exportedColors = colorRegistry.getColorRegistry().getColors().reduce((colors, entry) => { - const color = theme.getColor(entry.id); - if (color) { - colors['vscode-' + entry.id.replace('.', '-')] = color.toString(); - } - return colors; - }, {} as { [key: string]: string }); + private static readonly MEMOIZER = createMemoizer(); - const styles = { - 'vscode-font-family': '-apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif', - 'vscode-font-weight': 'normal', - 'vscode-font-size': '13px', - 'vscode-editor-font-family': editorFontFamily, - 'vscode-editor-font-weight': editorFontWeight, - 'vscode-editor-font-size': editorFontSize, - ...exportedColors - }; + constructor( + @IThemeService private readonly _themeService: IThemeService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + ) { + super(); + this._register(_themeService.onThemeChange(() => WebviewThemeDataProvider.MEMOIZER.clear())); + } - const activeTheme = ApiThemeClassName.fromTheme(theme); - return { styles, activeTheme }; + @WebviewThemeDataProvider.MEMOIZER + public getWebviewThemeData(): WebviewThemeData { + const configuration = this._configurationService.getValue('editor'); + const editorFontFamily = configuration.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; + const editorFontWeight = configuration.fontWeight || EDITOR_FONT_DEFAULTS.fontWeight; + const editorFontSize = configuration.fontSize || EDITOR_FONT_DEFAULTS.fontSize; + + const theme = this._themeService.getTheme(); + const exportedColors = colorRegistry.getColorRegistry().getColors().reduce((colors, entry) => { + const color = theme.getColor(entry.id); + if (color) { + colors['vscode-' + entry.id.replace('.', '-')] = color.toString(); + } + return colors; + }, {} as { [key: string]: string; }); + + const styles = { + 'vscode-font-family': '-apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif', + 'vscode-font-weight': 'normal', + 'vscode-font-size': '13px', + 'vscode-editor-font-family': editorFontFamily, + 'vscode-editor-font-weight': editorFontWeight, + 'vscode-editor-font-size': editorFontSize, + ...exportedColors + }; + + const activeTheme = ApiThemeClassName.fromTheme(theme); + return { styles, activeTheme }; + } } enum ApiThemeClassName { diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index c13df0b47da..5698a0565f5 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -11,7 +11,6 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { isMacintosh } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import * as modes from 'vs/editor/common/modes'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; @@ -22,7 +21,7 @@ import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader'; -import { getWebviewThemeData } from 'vs/workbench/contrib/webview/common/themeing'; +import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; import { registerFileProtocol } from 'vs/workbench/contrib/webview/electron-browser/webviewProtocols'; import { areWebviewInputOptionsEqual } from '../browser/webviewEditorService'; import { WebviewFindDelegate, WebviewFindWidget } from '../browser/webviewFindWidget'; @@ -39,7 +38,7 @@ interface IKeydownEvent { } type OnBeforeRequestDelegate = (details: OnBeforeRequestDetails) => Promise; -type OnHeadersReceivedDelegate = (details: OnHeadersReceivedDetails) => { cancel: boolean } | undefined; +type OnHeadersReceivedDelegate = (details: OnHeadersReceivedDetails) => { cancel: boolean; } | undefined; class WebviewSession extends Disposable { @@ -242,11 +241,11 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, constructor( options: WebviewOptions, contentOptions: WebviewContentOptions, + private readonly webviewThemeDataProvider: WebviewThemeDataProvider, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService, @IFileService fileService: IFileService, @ITunnelService tunnelService: ITunnelService, - @IConfigurationService private readonly _configurationService: IConfigurationService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @IEnvironmentService private readonly _environementService: IEnvironmentService, ) { @@ -430,7 +429,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, private readonly _onDidClickLink = this._register(new Emitter()); public readonly onDidClickLink = this._onDidClickLink.event; - private readonly _onDidScroll = this._register(new Emitter<{ scrollYPercentage: number }>()); + private readonly _onDidScroll = this._register(new Emitter<{ scrollYPercentage: number; }>()); public readonly onDidScroll = this._onDidScroll.event; private readonly _onDidUpdateState = this._register(new Emitter()); @@ -542,7 +541,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } type TelemetryClassification = { - extension?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' } + extension?: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; }; }; type TelemetryData = { extension?: string, @@ -559,7 +558,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } private style(theme: ITheme): void { - const { styles, activeTheme } = getWebviewThemeData(theme, this._configurationService); + const { styles, activeTheme } = this.webviewThemeDataProvider.getWebviewThemeData(); this._send('styles', { styles, activeTheme }); if (this._webviewFindWidget) { diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewService.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewService.ts index 49ec194e743..3c2c88c4c26 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewService.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewService.ts @@ -6,17 +6,22 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DynamicWebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay'; -import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement'; import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement'; +import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; import { ElectronWebviewBasedWebview } from 'vs/workbench/contrib/webview/electron-browser/webviewElement'; export class ElectronWebviewService implements IWebviewService { _serviceBrand: undefined; + private readonly webviewThemeDataProvider: WebviewThemeDataProvider; + constructor( @IInstantiationService private readonly _instantiationService: IInstantiationService, @IConfigurationService private readonly _configService: IConfigurationService, - ) { } + ) { + this.webviewThemeDataProvider = this._instantiationService.createInstance(WebviewThemeDataProvider); + } createWebview( id: string, @@ -25,9 +30,9 @@ export class ElectronWebviewService implements IWebviewService { ): WebviewElement { const useExternalEndpoint = this._configService.getValue('webview.experimental.useExternalEndpoint'); if (useExternalEndpoint) { - return this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions); + return this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions, this.webviewThemeDataProvider); } else { - return this._instantiationService.createInstance(ElectronWebviewBasedWebview, options, contentOptions); + return this._instantiationService.createInstance(ElectronWebviewBasedWebview, options, contentOptions, this.webviewThemeDataProvider); } } From b9693027bb40ec482e63af3e572713a5db30209c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:43:08 -0700 Subject: [PATCH 168/435] Use switch case --- src/vs/workbench/contrib/webview/common/themeing.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/webview/common/themeing.ts b/src/vs/workbench/contrib/webview/common/themeing.ts index 42c6801ebc6..f1ac357f34d 100644 --- a/src/vs/workbench/contrib/webview/common/themeing.ts +++ b/src/vs/workbench/contrib/webview/common/themeing.ts @@ -66,12 +66,10 @@ enum ApiThemeClassName { namespace ApiThemeClassName { export function fromTheme(theme: ITheme): ApiThemeClassName { - if (theme.type === LIGHT) { - return ApiThemeClassName.light; - } else if (theme.type === DARK) { - return ApiThemeClassName.dark; - } else { - return ApiThemeClassName.highContrast; + switch (theme.type) { + case LIGHT: return ApiThemeClassName.light; + case DARK: return ApiThemeClassName.dark; + default: return ApiThemeClassName.highContrast; } } } From 831800d6d817fe043714da3a99a94c9fed149968 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 13:56:14 -0700 Subject: [PATCH 169/435] Make sure we also change webview theme data when editor config changes --- .../contrib/webview/browser/webviewElement.ts | 4 +-- .../contrib/webview/common/themeing.ts | 26 ++++++++++++++++++- .../electron-browser/webviewElement.ts | 10 +++---- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 58c3b3b987d..3662830050b 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -12,7 +12,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; @@ -46,7 +45,6 @@ export class IFrameWebview extends Disposable implements Webview { options: WebviewOptions, contentOptions: WebviewContentOptions, private readonly webviewThemeDataProvider: WebviewThemeDataProvider, - @IThemeService themeService: IThemeService, @ITunnelService tunnelService: ITunnelService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IFileService private readonly fileService: IFileService, @@ -148,7 +146,7 @@ export class IFrameWebview extends Disposable implements Webview { }); this.style(); - this._register(themeService.onThemeChange(this.style, this)); + this._register(webviewThemeDataProvider.onThemeDataChanged(this.style, this)); } private get externalEndpoint(): string { diff --git a/src/vs/workbench/contrib/webview/common/themeing.ts b/src/vs/workbench/contrib/webview/common/themeing.ts index f1ac357f34d..9b2684fd3ae 100644 --- a/src/vs/workbench/contrib/webview/common/themeing.ts +++ b/src/vs/workbench/contrib/webview/common/themeing.ts @@ -9,6 +9,7 @@ import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/ed import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import * as colorRegistry from 'vs/platform/theme/common/colorRegistry'; import { DARK, ITheme, IThemeService, LIGHT } from 'vs/platform/theme/common/themeService'; +import { Emitter } from 'vs/base/common/event'; interface WebviewThemeData { readonly activeTheme: string; @@ -17,14 +18,32 @@ interface WebviewThemeData { export class WebviewThemeDataProvider extends Disposable { + private static readonly MEMOIZER = createMemoizer(); + private readonly _onThemeDataChanged = this._register(new Emitter()); + public readonly onThemeDataChanged = this._onThemeDataChanged.event; + constructor( @IThemeService private readonly _themeService: IThemeService, @IConfigurationService private readonly _configurationService: IConfigurationService, ) { super(); - this._register(_themeService.onThemeChange(() => WebviewThemeDataProvider.MEMOIZER.clear())); + + this._register(this._themeService.onThemeChange(() => { + this.reset(); + })); + + const webviewConfigurationKeys = ['editor.fontFamily', 'editor.fontWeight', 'editor.fontSize']; + this._register(this._configurationService.onDidChangeConfiguration(e => { + if (webviewConfigurationKeys.some(key => e.affectsConfiguration(key))) { + this.reset(); + } + })); + } + + public getTheme(): ITheme { + return this._themeService.getTheme(); } @WebviewThemeDataProvider.MEMOIZER @@ -56,6 +75,11 @@ export class WebviewThemeDataProvider extends Disposable { const activeTheme = ApiThemeClassName.fromTheme(theme); return { styles, activeTheme }; } + + private reset() { + WebviewThemeDataProvider.MEMOIZER.clear(); + this._onThemeDataChanged.fire(); + } } enum ApiThemeClassName { diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 5698a0565f5..ab5c8d3df87 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -17,7 +17,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader'; @@ -396,8 +396,8 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, })); } - this.style(themeService.getTheme()); - this._register(themeService.onThemeChange(this.style, this)); + this.style(); + this._register(webviewThemeDataProvider.onThemeDataChanged(this.style, this)); } public mountTo(parent: HTMLElement) { @@ -557,12 +557,12 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, this._send('message', data); } - private style(theme: ITheme): void { + private style(): void { const { styles, activeTheme } = this.webviewThemeDataProvider.getWebviewThemeData(); this._send('styles', { styles, activeTheme }); if (this._webviewFindWidget) { - this._webviewFindWidget.updateTheme(theme); + this._webviewFindWidget.updateTheme(this.webviewThemeDataProvider.getTheme()); } } From 30120e4db611c7fe693ea278fdd024c3a832ab9e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 14:11:52 -0700 Subject: [PATCH 170/435] Dont pass undefined as boolean For #81574 --- src/vs/workbench/browser/parts/compositePart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index adac882f1d3..9531cb8a75b 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -168,7 +168,7 @@ export abstract class CompositePart extends Part { // Instantiate composite from registry otherwise const compositeDescriptor = this.registry.getComposite(id); if (compositeDescriptor) { - const compositeProgressIndicator = this.instantiationService.createInstance(CompositeProgressIndicator, this.progressBar, compositeDescriptor.id, isActive); + const compositeProgressIndicator = this.instantiationService.createInstance(CompositeProgressIndicator, this.progressBar, compositeDescriptor.id, !!isActive); const compositeInstantiationService = this.instantiationService.createChild(new ServiceCollection( [IEditorProgressService, compositeProgressIndicator] // provide the editor progress service for any editors instantiated within the composite )); From 92514c469c1507e21ae3fb264f7331e91fab737f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 14:25:55 -0700 Subject: [PATCH 171/435] Fix a few more issues related to #81574 --- src/vs/workbench/common/editor/editorGroup.ts | 2 +- .../contrib/feedback/browser/feedbackStatusbarItem.ts | 6 +++++- .../contrib/webview/browser/webviewEditorService.ts | 5 ++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/common/editor/editorGroup.ts b/src/vs/workbench/common/editor/editorGroup.ts index a1447c830ca..19255049976 100644 --- a/src/vs/workbench/common/editor/editorGroup.ts +++ b/src/vs/workbench/common/editor/editorGroup.ts @@ -102,7 +102,7 @@ export class EditorGroup extends Disposable { private focusRecentEditorAfterClose: boolean | undefined; constructor( - labelOrSerializedGroup: ISerializedEditorGroup, + labelOrSerializedGroup: ISerializedEditorGroup | undefined, @IInstantiationService private readonly instantiationService: IInstantiationService, @IConfigurationService private readonly configurationService: IConfigurationService ) { diff --git a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts index 745b55f7806..cfd4b53068a 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts @@ -71,7 +71,11 @@ export class FeedbackStatusbarConribution extends Disposable implements IWorkben if (!this.dropdown) { const statusContainr = document.getElementById('status.feedback'); if (statusContainr) { - this.dropdown = this._register(this.instantiationService.createInstance(FeedbackDropdown, statusContainr.getElementsByClassName('octicon').item(0), { + const icon = statusContainr.getElementsByClassName('octicon').item(0) as HTMLElement | null; + if (!icon) { + throw new Error('Could not find icon'); + } + this.dropdown = this._register(this.instantiationService.createInstance(FeedbackDropdown, icon, { contextViewProvider: this.contextViewService, feedbackService: this.instantiationService.createInstance(TwitterFeedbackService), onFeedbackVisibilityChange: visible => this.entry!.update(this.getStatusEntry(visible)) diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index bd865990708..0bc180e7e87 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -8,7 +8,7 @@ import { IDisposable, toDisposable, UnownedDisposable } from 'vs/base/common/lif import { values } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { GroupIdentifier } from 'vs/workbench/common/editor'; import { IWebviewService, WebviewOptions, WebviewContentOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -131,7 +131,6 @@ export class WebviewEditorService implements IWebviewEditorService { constructor( @IEditorService private readonly _editorService: IEditorService, - @IInstantiationService private readonly _instantiationService: IInstantiationService, @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, @IWebviewService private readonly _webviewService: IWebviewService, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @@ -150,7 +149,7 @@ export class WebviewEditorService implements IWebviewEditorService { ): WebviewInput { const webview = this.createWebiew(id, extension, options); - const webviewInput = this._instantiationService.createInstance(WebviewInput, id, viewType, title, new UnownedDisposable(webview), undefined); + const webviewInput = new WebviewInput(id, viewType, title, new UnownedDisposable(webview)); this._editorService.openEditor(webviewInput, { pinned: true, preserveFocus: showOptions.preserveFocus, From a7ddb97e919d78998ef02e67df5aa340a7259e10 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 14:43:18 -0700 Subject: [PATCH 172/435] Fix strict property init in parameterHintWidget For #78168 --- .../parameterHints/parameterHintsWidget.ts | 104 +++++++++++------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index 2b1b9c8fbfa..a6040059de6 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -34,13 +34,17 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, private readonly model = this._register(new MutableDisposable()); private readonly keyVisible: IContextKey; private readonly keyMultipleSignatures: IContextKey; - private element: HTMLElement; - private signature: HTMLElement; - private docs: HTMLElement; - private overloads: HTMLElement; - private visible: boolean; - private announcedLabel: string | null; - private scrollbar: DomScrollableElement; + + private domNodes?: { + readonly element: HTMLElement; + readonly signature: HTMLElement; + readonly docs: HTMLElement; + readonly overloads: HTMLElement; + readonly scrollbar: DomScrollableElement; + }; + + private visible: boolean = false; + private announcedLabel: string | null = null; // Editor.IContentWidget.allowEditorOverflow allowEditorOverflow = true; @@ -56,7 +60,6 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, this.model.value = new ParameterHintsModel(editor); this.keyVisible = Context.Visible.bindTo(contextKeyService); this.keyMultipleSignatures = Context.MultipleSignatures.bindTo(contextKeyService); - this.visible = false; this._register(this.model.value.onChangedHints(newParameterHints => { if (newParameterHints) { @@ -69,8 +72,8 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, } private createParamaterHintDOMNodes() { - this.element = $('.editor-widget.parameter-hints-widget'); - const wrapper = dom.append(this.element, $('.wrapper')); + const element = $('.editor-widget.parameter-hints-widget'); + const wrapper = dom.append(element, $('.wrapper')); wrapper.tabIndex = -1; const buttons = dom.append(wrapper, $('.buttons')); @@ -83,21 +86,29 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, const onNextClick = stop(domEvent(next, 'click')); this._register(onNextClick(this.next, this)); - this.overloads = dom.append(wrapper, $('.overloads')); + const overloads = dom.append(wrapper, $('.overloads')); const body = $('.body'); - this.scrollbar = new DomScrollableElement(body, {}); - this._register(this.scrollbar); - wrapper.appendChild(this.scrollbar.getDomNode()); + const scrollbar = new DomScrollableElement(body, {}); + this._register(scrollbar); + wrapper.appendChild(scrollbar.getDomNode()); - this.signature = dom.append(body, $('.signature')); + const signature = dom.append(body, $('.signature')); + const docs = dom.append(body, $('.docs')); - this.docs = dom.append(body, $('.docs')); + element.style.userSelect = 'text'; + + this.domNodes = { + element, + signature, + overloads, + docs, + scrollbar, + }; this.editor.addContentWidget(this); this.hide(); - this.element.style.userSelect = 'text'; this._register(this.editor.onDidChangeCursorSelection(e => { if (this.visible) { this.editor.layoutContentWidget(this); @@ -105,8 +116,11 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, })); const updateFont = () => { + if (!this.domNodes) { + return; + } const fontInfo = this.editor.getOption(EditorOption.fontInfo); - this.element.style.fontSize = `${fontInfo.fontSize}px`; + this.domNodes.element.style.fontSize = `${fontInfo.fontSize}px`; }; updateFont(); @@ -124,13 +138,17 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, return; } - if (!this.element) { + if (!this.domNodes) { this.createParamaterHintDOMNodes(); } this.keyVisible.set(true); this.visible = true; - setTimeout(() => dom.addClass(this.element, 'visible'), 100); + setTimeout(() => { + if (this.domNodes) { + dom.addClass(this.domNodes.element, 'visible'); + } + }, 100); this.editor.layoutContentWidget(this); } @@ -139,14 +157,12 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, return; } - if (!this.element) { - this.createParamaterHintDOMNodes(); - } - this.keyVisible.reset(); this.visible = false; this.announcedLabel = null; - dom.removeClass(this.element, 'visible'); + if (this.domNodes) { + dom.removeClass(this.domNodes.element, 'visible'); + } this.editor.layoutContentWidget(this); } @@ -161,12 +177,16 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, } private render(hints: modes.SignatureHelp): void { + if (!this.domNodes) { + return; + } + const multiple = hints.signatures.length > 1; - dom.toggleClass(this.element, 'multiple', multiple); + dom.toggleClass(this.domNodes.element, 'multiple', multiple); this.keyMultipleSignatures.set(multiple); - this.signature.innerHTML = ''; - this.docs.innerHTML = ''; + this.domNodes.signature.innerHTML = ''; + this.domNodes.docs.innerHTML = ''; const signature = hints.signatures[hints.activeSignature]; @@ -174,7 +194,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, return; } - const code = dom.append(this.signature, $('.code')); + const code = dom.append(this.domNodes.signature, $('.code')); const hasParameters = signature.parameters.length > 0; const fontInfo = this.editor.getOption(EditorOption.fontInfo); @@ -203,17 +223,17 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, this.renderDisposeables.add(renderedContents); documentation.appendChild(renderedContents.element); } - dom.append(this.docs, $('p', {}, documentation)); + dom.append(this.domNodes.docs, $('p', {}, documentation)); } if (signature.documentation === undefined) { /** no op */ } else if (typeof signature.documentation === 'string') { - dom.append(this.docs, $('p', {}, signature.documentation)); + dom.append(this.domNodes.docs, $('p', {}, signature.documentation)); } else { const renderedContents = this.markdownRenderer.render(signature.documentation); dom.addClass(renderedContents.element, 'markdown-docs'); this.renderDisposeables.add(renderedContents); - dom.append(this.docs, renderedContents.element); + dom.append(this.domNodes.docs, renderedContents.element); } let hasDocs = false; @@ -230,8 +250,8 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, hasDocs = true; } - dom.toggleClass(this.signature, 'has-docs', hasDocs); - dom.toggleClass(this.docs, 'empty', !hasDocs); + dom.toggleClass(this.domNodes.signature, 'has-docs', hasDocs); + dom.toggleClass(this.domNodes.docs, 'empty', !hasDocs); let currentOverload = String(hints.activeSignature + 1); @@ -239,7 +259,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, currentOverload += `/${hints.signatures.length}`; } - this.overloads.textContent = currentOverload; + this.domNodes.overloads.textContent = currentOverload; if (activeParameter) { const labelToAnnounce = this.getParameterLabel(signature, hints.activeParameter); @@ -253,7 +273,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, } this.editor.layoutContentWidget(this); - this.scrollbar.scanDomNode(); + this.domNodes.scrollbar.scanDomNode(); } private renderParameters(parent: HTMLElement, signature: modes.SignatureInformation, currentParameter: number): void { @@ -317,7 +337,10 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, } getDomNode(): HTMLElement { - return this.element; + if (!this.domNodes) { + this.createParamaterHintDOMNodes(); + } + return this.domNodes!.element; } getId(): string { @@ -331,10 +354,13 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget, } private updateMaxHeight(): void { + if (!this.domNodes) { + return; + } const height = Math.max(this.editor.getLayoutInfo().height / 4, 250); const maxHeight = `${height}px`; - this.element.style.maxHeight = maxHeight; - const wrapper = this.element.getElementsByClassName('wrapper') as HTMLCollectionOf; + this.domNodes.element.style.maxHeight = maxHeight; + const wrapper = this.domNodes.element.getElementsByClassName('wrapper') as HTMLCollectionOf; if (wrapper.length) { wrapper[0].style.maxHeight = maxHeight; } From 7e70b1dda03b102094c7730b65ed8568a573834a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 14:58:42 -0700 Subject: [PATCH 173/435] Mark that preferredEncoding can be undefined / not initialized Part of #78168 --- .../workbench/browser/parts/editor/editor.contribution.ts | 2 +- src/vs/workbench/browser/parts/editor/editorStatus.ts | 6 +++--- src/vs/workbench/common/editor.ts | 2 +- src/vs/workbench/common/editor/untitledEditorInput.ts | 2 +- src/vs/workbench/common/editor/untitledEditorModel.ts | 4 ++-- .../contrib/files/common/editors/fileEditorInput.ts | 8 ++++---- .../editor/test/browser/editorGroupsService.test.ts | 2 +- .../services/editor/test/browser/editorService.test.ts | 2 +- .../services/textfile/common/textFileEditorModel.ts | 4 ++-- src/vs/workbench/services/textfile/common/textfiles.ts | 2 +- src/vs/workbench/test/common/editor/editorGroups.test.ts | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 5f4afb20bc2..717579e2883 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -106,7 +106,7 @@ interface ISerializedUntitledEditorInput { resource: string; resourceJSON: object; modeId: string | undefined; - encoding: string; + encoding: string | undefined; } // Register Editor Input Factory diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 76ea1208dbf..b42ee997242 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -54,7 +54,7 @@ import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatus class SideBySideEditorEncodingSupport implements IEncodingSupport { constructor(private master: IEncodingSupport, private details: IEncodingSupport) { } - getEncoding(): string { + getEncoding(): string | undefined { return this.master.getEncoding(); // always report from modified (right hand) side } @@ -352,7 +352,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { return this.quickInputService.pick([{ label: nls.localize('noWritableCodeEditor', "The active code editor is read-only.") }]); } - const picks: QuickPickInput[] = [ + const picks: QuickPickInput[] = [ activeTextEditorWidget.getAction(IndentUsingSpaces.ID), activeTextEditorWidget.getAction(IndentUsingTabs.ID), activeTextEditorWidget.getAction(DetectIndentation.ID), @@ -778,7 +778,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { const encodingSupport: IEncodingSupport | null = e.input ? toEditorWithEncodingSupport(e.input) : null; if (encodingSupport) { const rawEncoding = encodingSupport.getEncoding(); - const encodingInfo = SUPPORTED_ENCODINGS[rawEncoding]; + const encodingInfo = typeof rawEncoding === 'string' ? SUPPORTED_ENCODINGS[rawEncoding] : undefined; if (encodingInfo) { info.encoding = encodingInfo.labelShort; // if we have a label, take it from there } else { diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index c30bfed1f19..1331b459d13 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -499,7 +499,7 @@ export interface IEncodingSupport { /** * Gets the encoding of the input if known. */ - getEncoding(): string; + getEncoding(): string | undefined; /** * Sets the encoding for the input for saving. diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 1c021309268..1ed96be6723 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -177,7 +177,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport return this.getName(); } - getEncoding(): string { + getEncoding(): string | undefined { if (this.cachedModel) { return this.cachedModel.getEncoding(); } diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 57a77b7267b..3c6570c29a1 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -33,7 +33,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private dirty: boolean = false; private versionId: number = 0; private readonly contentChangeEventScheduler: RunOnceScheduler; - private configuredEncoding: string; + private configuredEncoding?: string; constructor( private readonly preferredMode: string, @@ -87,7 +87,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin return this.preferredMode; } - getEncoding(): string { + getEncoding(): string | undefined { return this.preferredEncoding || this.configuredEncoding; } diff --git a/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts index 662bcc8347a..c874b1342a2 100644 --- a/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts @@ -31,8 +31,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { private static readonly MEMOIZER = createMemoizer(); - private preferredEncoding: string; - private preferredMode: string; + private preferredEncoding: string | undefined; + private preferredMode: string | undefined; private forceOpenAs: ForceOpenAs = ForceOpenAs.None; @@ -91,7 +91,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { return this.resource; } - getEncoding(): string { + getEncoding(): string | undefined { const textModel = this.textFileService.models.get(this.resource); if (textModel) { return textModel.getEncoding(); @@ -100,7 +100,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { return this.preferredEncoding; } - getPreferredEncoding(): string { + getPreferredEncoding(): string | undefined { return this.preferredEncoding; } diff --git a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts index 54096dfc116..98e93a57adb 100644 --- a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts @@ -43,7 +43,7 @@ export class TestEditorInput extends EditorInput implements IFileEditorInput { resolve(): Promise { return Promise.resolve(null); } matches(other: TestEditorInput): boolean { return other && this.resource.toString() === other.resource.toString() && other instanceof TestEditorInput; } setEncoding(encoding: string) { } - getEncoding(): string { return null!; } + getEncoding() { return undefined; } setPreferredEncoding(encoding: string) { } setMode(mode: string) { } setPreferredMode(mode: string) { } 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 f3c781424b3..9601ae63122 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -57,7 +57,7 @@ export class TestEditorInput extends EditorInput implements IFileEditorInput { resolve(): Promise { return !this.fails ? Promise.resolve(null) : Promise.reject(new Error('fails')); } matches(other: TestEditorInput): boolean { return other && other.resource && this.resource.toString() === other.resource.toString() && other instanceof TestEditorInput; } setEncoding(encoding: string) { } - getEncoding(): string { return null!; } + getEncoding() { return undefined; } setPreferredEncoding(encoding: string) { } setMode(mode: string) { } setPreferredMode(mode: string) { } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 900b4f6eed8..5d39163ccdb 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -992,7 +992,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } } - updatePreferredEncoding(encoding: string): void { + updatePreferredEncoding(encoding: string | undefined): void { if (!this.isNewEncoding(encoding)) { return; } @@ -1003,7 +1003,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil this._onDidStateChange.fire(StateChange.ENCODING); } - private isNewEncoding(encoding: string): boolean { + private isNewEncoding(encoding: string | undefined): boolean { if (this.preferredEncoding === encoding) { return false; // return early if the encoding is already the same } diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index 568ad75afca..1293d717f3d 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -463,7 +463,7 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport hasState(state: ModelState): boolean; - updatePreferredEncoding(encoding: string): void; + updatePreferredEncoding(encoding: string | undefined): void; save(options?: ISaveOptions): Promise; diff --git a/src/vs/workbench/test/common/editor/editorGroups.test.ts b/src/vs/workbench/test/common/editor/editorGroups.test.ts index 652994bc809..46805b2c9da 100644 --- a/src/vs/workbench/test/common/editor/editorGroups.test.ts +++ b/src/vs/workbench/test/common/editor/editorGroups.test.ts @@ -112,7 +112,7 @@ class TestFileEditorInput extends EditorInput implements IFileEditorInput { getTypeId() { return 'testFileEditorInputForGroups'; } resolve(): Promise { return Promise.resolve(null!); } setEncoding(encoding: string) { } - getEncoding(): string { return null!; } + getEncoding() { return undefined; } setPreferredEncoding(encoding: string) { } getResource(): URI { return this.resource; } setForceOpenAsBinary(): void { } From dc0ab500359c019bab5fd6bc266a8113bb0bbd53 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 15:22:42 -0700 Subject: [PATCH 174/435] Use isEqual for comparing uris in more places vs .toString() --- .../contrib/goToDefinition/goToDefinitionCommands.ts | 3 ++- .../goToDefinition/goToDefinitionResultsNavigation.ts | 3 ++- src/vs/editor/contrib/gotoError/gotoError.ts | 9 +++++---- .../editor/contrib/referenceSearch/referencesWidget.ts | 4 ++-- src/vs/workbench/api/browser/mainThreadCodeInsets.ts | 3 ++- src/vs/workbench/browser/parts/editor/editorStatus.ts | 4 ++-- .../contrib/preferences/browser/preferencesWidgets.ts | 7 ++++--- .../welcome/walkThrough/browser/walkThroughInput.ts | 5 +++-- .../workbench/services/editor/browser/editorService.ts | 4 ++-- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/vs/editor/contrib/goToDefinition/goToDefinitionCommands.ts b/src/vs/editor/contrib/goToDefinition/goToDefinitionCommands.ts index 1844a9f3456..e234b8d299d 100644 --- a/src/vs/editor/contrib/goToDefinition/goToDefinitionCommands.ts +++ b/src/vs/editor/contrib/goToDefinition/goToDefinitionCommands.ts @@ -31,6 +31,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { EditorStateCancellationTokenSource, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState'; import { ISymbolNavigationService } from 'vs/editor/contrib/goToDefinition/goToDefinitionResultsNavigation'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { isEqual } from 'vs/base/common/resources'; export class DefinitionActionConfig { @@ -84,7 +85,7 @@ export class DefinitionAction extends EditorAction { } const newLen = result.push(reference); if (this._configuration.filterCurrent - && reference.uri.toString() === model.uri.toString() + && isEqual(reference.uri, model.uri) && Range.containsPosition(reference.range, pos) && idxOfCurrent === -1 ) { diff --git a/src/vs/editor/contrib/goToDefinition/goToDefinitionResultsNavigation.ts b/src/vs/editor/contrib/goToDefinition/goToDefinitionResultsNavigation.ts index e52bc043383..bbf2cddd212 100644 --- a/src/vs/editor/contrib/goToDefinition/goToDefinitionResultsNavigation.ts +++ b/src/vs/editor/contrib/goToDefinition/goToDefinitionResultsNavigation.ts @@ -18,6 +18,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { isEqual } from 'vs/base/common/resources'; export const ctxHasSymbols = new RawContextKey('hasSymbols', false); @@ -92,7 +93,7 @@ class SymbolNavigationService implements ISymbolNavigationService { let seenUri: boolean = false; let seenPosition: boolean = false; for (const reference of refModel.references) { - if (reference.uri.toString() === model.uri.toString()) { + if (isEqual(reference.uri, model.uri)) { seenUri = true; seenPosition = seenPosition || Range.containsPosition(reference.range, position); } else if (seenUri) { diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index f2ebe3575c3..c552b5f4406 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -26,6 +26,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { Action } from 'vs/base/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { isEqual } from 'vs/base/common/resources'; class MarkerModel { @@ -310,7 +311,7 @@ export class MarkerController implements editorCommon.IEditorContribution { } private _onMarkerChanged(changedResources: URI[]): void { - let editorModel = this._editor.getModel(); + const editorModel = this._editor.getModel(); if (!editorModel) { return; } @@ -319,7 +320,7 @@ export class MarkerController implements editorCommon.IEditorContribution { return; } - if (!changedResources.some(r => editorModel!.uri.toString() === r.toString())) { + if (!changedResources.some(r => isEqual(editorModel.uri, r))) { return; } this._model.setMarkers(this._getMarkers()); @@ -371,7 +372,7 @@ class MarkerNavigationAction extends EditorAction { return Promise.resolve(undefined); } - let editorModel = editor.getModel(); + const editorModel = editor.getModel(); if (!editorModel) { return Promise.resolve(undefined); } @@ -389,7 +390,7 @@ class MarkerNavigationAction extends EditorAction { } let newMarker = markers[idx]; - if (newMarker.resource.toString() === editorModel!.uri.toString()) { + if (isEqual(newMarker.resource, editorModel.uri)) { // the next `resource` is this resource which // means we cycle within this file model.move(this._isNext, true); diff --git a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts index 38f2d1151db..a152a855820 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts @@ -10,7 +10,7 @@ import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { dispose, IDisposable, IReference, DisposableStore } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; -import { basenameOrAuthority, dirname } from 'vs/base/common/resources'; +import { basenameOrAuthority, dirname, isEqual } from 'vs/base/common/resources'; import 'vs/css!./media/referencesWidget'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; @@ -66,7 +66,7 @@ class DecorationsManager implements IDisposable { const model = this._editor.getModel(); if (model) { for (const ref of this._model.groups) { - if (ref.uri.toString() === model.uri.toString()) { + if (isEqual(ref.uri, model.uri)) { this._addDecorations(ref); return; } diff --git a/src/vs/workbench/api/browser/mainThreadCodeInsets.ts b/src/vs/workbench/api/browser/mainThreadCodeInsets.ts index cefcf818f89..b504c55e3b2 100644 --- a/src/vs/workbench/api/browser/mainThreadCodeInsets.ts +++ b/src/vs/workbench/api/browser/mainThreadCodeInsets.ts @@ -12,6 +12,7 @@ import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/br import { DisposableStore } from 'vs/base/common/lifecycle'; import { IActiveCodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { isEqual } from 'vs/base/common/resources'; // todo@joh move these things back into something like contrib/insets class EditorWebviewZone implements IViewZone { @@ -75,7 +76,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape { id = id.substr(0, id.indexOf(',')); //todo@joh HACK for (const candidate of this._editorService.listCodeEditors()) { - if (candidate.getId() === id && candidate.hasModel() && candidate.getModel()!.uri.toString() === URI.revive(uri).toString()) { + if (candidate.getId() === id && candidate.hasModel() && isEqual(candidate.getModel().uri, URI.revive(uri))) { editor = candidate; break; } diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index b42ee997242..647abff323a 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/editorstatus'; import * as nls from 'vs/nls'; import { runAtThisOrScheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; import { format } from 'vs/base/common/strings'; -import { extname, basename } from 'vs/base/common/resources'; +import { extname, basename, isEqual } from 'vs/base/common/resources'; import { areFunctions, withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { Action } from 'vs/base/common/actions'; @@ -794,7 +794,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { const activeControl = this.editorService.activeControl; if (activeControl) { const activeResource = toResource(activeControl.input, { supportSideBySide: SideBySideEditor.MASTER }); - if (activeResource && activeResource.toString() === resource.toString()) { + if (activeResource && isEqual(activeResource, resource)) { return this.onEncodingChange(activeControl); // only update if the encoding changed for the active resource } } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index 89ea848b7f3..bec3cdc2210 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -34,6 +34,7 @@ import { PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIV import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { isEqual } from 'vs/base/common/resources'; export class SettingsHeaderWidget extends Widget implements IViewZone { @@ -387,7 +388,7 @@ export class FolderSettingsActionViewItem extends BaseActionViewItem { const oldFolder = this._folder; const workspace = this.contextService.getWorkspace(); if (oldFolder) { - this._folder = workspace.folders.filter(folder => folder.uri.toString() === oldFolder.uri.toString())[0] || workspace.folders[0]; + this._folder = workspace.folders.filter(folder => isEqual(folder.uri, oldFolder.uri))[0] || workspace.folders[0]; } this._folder = this._folder ? this._folder : workspace.folders.length === 1 ? workspace.folders[0] : null; @@ -440,7 +441,7 @@ export class FolderSettingsActionViewItem extends BaseActionViewItem { return { id: 'folderSettingsTarget' + index, label: this.labelWithCount(folder.name, folderCount), - checked: this.folder && this.folder.uri.toString() === folder.uri.toString(), + checked: this.folder && isEqual(this.folder.uri, folder.uri), enabled: true, run: () => this._action.run(folder) }; @@ -574,7 +575,7 @@ export class SettingsTargetsWidget extends Widget { const isSameTarget = this.settingsTarget === settingsTarget || settingsTarget instanceof URI && this.settingsTarget instanceof URI && - this.settingsTarget.toString() === settingsTarget.toString(); + isEqual(this.settingsTarget, settingsTarget); if (!isSameTarget) { this.settingsTarget = settingsTarget; diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts index 6d69a2758f1..2b7a9668bd2 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts @@ -10,6 +10,7 @@ import { IReference } from 'vs/base/common/lifecycle'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import * as marked from 'vs/base/common/marked/marked'; import { Schemas } from 'vs/base/common/network'; +import { isEqual } from 'vs/base/common/resources'; export class WalkThroughModel extends EditorModel { @@ -78,7 +79,7 @@ export class WalkThroughInput extends EditorInput { return this.options.telemetryFrom; } - getTelemetryDescriptor(): { [key: string]: unknown } { + getTelemetryDescriptor(): { [key: string]: unknown; } { const descriptor = super.getTelemetryDescriptor(); descriptor['target'] = this.getTelemetryFrom(); /* __GDPR__FRAGMENT__ @@ -130,7 +131,7 @@ export class WalkThroughInput extends EditorInput { let otherResourceEditorInput = otherInput; // Compare by properties - return otherResourceEditorInput.options.resource.toString() === this.options.resource.toString(); + return isEqual(otherResourceEditorInput.options.resource, this.options.resource); } return false; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index a056de4bf9d..9eb8d8c8a9e 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -15,7 +15,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; -import { basename } from 'vs/base/common/resources'; +import { basename, isEqual } from 'vs/base/common/resources'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { localize } from 'vs/nls'; import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -464,7 +464,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { } const resourceInput = editor as IResourceInput | IUntitledResourceInput; - if (resourceInput.resource && resource.toString() === resourceInput.resource.toString()) { + if (resourceInput.resource && isEqual(resource, resourceInput.resource)) { return editorInGroup; } } From e1011ffcc8fcc9d506a0f23aedadc71ba86a65b1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 15:24:25 -0700 Subject: [PATCH 175/435] Marking event properties as readonly --- .../editor/contrib/referenceSearch/referencesWidget.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts index a152a855820..7a5bae4a3db 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts @@ -158,8 +158,8 @@ class DecorationsManager implements IDisposable { } export class LayoutData { - ratio: number = 0.7; - heightInLines: number = 18; + public ratio: number = 0.7; + public heightInLines: number = 18; static fromJSON(raw: string): LayoutData { let ratio: number | undefined; @@ -179,9 +179,9 @@ export class LayoutData { } export interface SelectionEvent { - kind: 'goto' | 'show' | 'side' | 'open'; - source: 'editor' | 'tree' | 'title'; - element?: Location; + readonly kind: 'goto' | 'show' | 'side' | 'open'; + readonly source: 'editor' | 'tree' | 'title'; + readonly element?: Location; } export const ctxReferenceWidgetSearchTreeFocused = new RawContextKey('referenceSearchTreeFocused', true); From a967c8ada39745a457d0a6c957d513f882617585 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 15:31:21 -0700 Subject: [PATCH 176/435] Move js/ts json validation to js/ts language features extension Fixes #73336 --- extensions/javascript/package.json | 32 +---------- extensions/typescript-basics/package.json | 30 ---------- .../typescript-language-features/package.json | 56 +++++++++++++++++++ .../schemas/jsconfig.schema.json | 0 .../schemas/tsconfig.schema.json | 0 5 files changed, 57 insertions(+), 61 deletions(-) rename extensions/{javascript => typescript-language-features}/schemas/jsconfig.schema.json (100%) rename extensions/{typescript-basics => typescript-language-features}/schemas/tsconfig.schema.json (100%) diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index 6909de1400f..8d315c45835 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -98,36 +98,6 @@ "language": "javascriptreact", "path": "./snippets/javascript.json" } - ], - "jsonValidation": [ - { - "fileMatch": ".bowerrc", - "url": "https://schemastore.azurewebsites.net/schemas/json/bowerrc.json" - }, - { - "fileMatch": ".babelrc", - "url": "https://schemastore.azurewebsites.net/schemas/json/babelrc.json" - }, - { - "fileMatch": ".babelrc.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/babelrc.json" - }, - { - "fileMatch": "jsconfig.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/jsconfig.json" - }, - { - "fileMatch": "jsconfig.json", - "url": "./schemas/jsconfig.schema.json" - }, - { - "fileMatch": "jsconfig.*.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/jsconfig.json" - }, - { - "fileMatch": "jsconfig.*.json", - "url": "./schemas/jsconfig.schema.json" - } ] } -} \ No newline at end of file +} diff --git a/extensions/typescript-basics/package.json b/extensions/typescript-basics/package.json index 185a8a2bc71..0d162fcbaa2 100644 --- a/extensions/typescript-basics/package.json +++ b/extensions/typescript-basics/package.json @@ -98,36 +98,6 @@ "language": "typescriptreact", "path": "./snippets/typescript.json" } - ], - "jsonValidation": [ - { - "fileMatch": "tsconfig.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" - }, - { - "fileMatch": "tsconfig.json", - "url": "./schemas/tsconfig.schema.json" - }, - { - "fileMatch": "tsconfig.*.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" - }, - { - "fileMatch": "tsconfig-*.json", - "url": "./schemas/tsconfig.schema.json" - }, - { - "fileMatch": "tsconfig-*.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" - }, - { - "fileMatch": "tsconfig.*.json", - "url": "./schemas/tsconfig.schema.json" - }, - { - "fileMatch": "typings.json", - "url": "https://schemastore.azurewebsites.net/schemas/json/typings.json" - } ] } } diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 0b18f854feb..5b9d01c69d1 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -53,6 +53,62 @@ { "fileMatch": "package.json", "url": "./schemas/package.schema.json" + }, + { + "fileMatch": "tsconfig.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" + }, + { + "fileMatch": "tsconfig.json", + "url": "./schemas/tsconfig.schema.json" + }, + { + "fileMatch": "tsconfig.*.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" + }, + { + "fileMatch": "tsconfig-*.json", + "url": "./schemas/tsconfig.schema.json" + }, + { + "fileMatch": "tsconfig-*.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json" + }, + { + "fileMatch": "tsconfig.*.json", + "url": "./schemas/tsconfig.schema.json" + }, + { + "fileMatch": "typings.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/typings.json" + }, + { + "fileMatch": ".bowerrc", + "url": "https://schemastore.azurewebsites.net/schemas/json/bowerrc.json" + }, + { + "fileMatch": ".babelrc", + "url": "https://schemastore.azurewebsites.net/schemas/json/babelrc.json" + }, + { + "fileMatch": ".babelrc.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/babelrc.json" + }, + { + "fileMatch": "jsconfig.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/jsconfig.json" + }, + { + "fileMatch": "jsconfig.json", + "url": "./schemas/jsconfig.schema.json" + }, + { + "fileMatch": "jsconfig.*.json", + "url": "https://schemastore.azurewebsites.net/schemas/json/jsconfig.json" + }, + { + "fileMatch": "jsconfig.*.json", + "url": "./schemas/jsconfig.schema.json" } ], "configuration": { diff --git a/extensions/javascript/schemas/jsconfig.schema.json b/extensions/typescript-language-features/schemas/jsconfig.schema.json similarity index 100% rename from extensions/javascript/schemas/jsconfig.schema.json rename to extensions/typescript-language-features/schemas/jsconfig.schema.json diff --git a/extensions/typescript-basics/schemas/tsconfig.schema.json b/extensions/typescript-language-features/schemas/tsconfig.schema.json similarity index 100% rename from extensions/typescript-basics/schemas/tsconfig.schema.json rename to extensions/typescript-language-features/schemas/tsconfig.schema.json From 4ddddcfb6deb98ffc109369fc859b4df8b81d558 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 4 Oct 2019 16:20:24 -0700 Subject: [PATCH 177/435] Fix strictFunctionTypes errors in terminalInstance Part of #81574 --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index d3dde9111c4..da54984afdc 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -507,7 +507,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return false; }); } - this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, this._processManager, this._configHelper); + this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, xterm, this._processManager, this._configHelper); }); this._commandTrackerAddon = new CommandTrackerAddon(); From a0c6566f87c49dcfe8e79e642d75009ba0628877 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 4 Oct 2019 16:32:51 -0700 Subject: [PATCH 178/435] Fix strictFunctionTypes errors in terminalService Part of #81574 --- .../contrib/terminal/browser/terminalInstance.ts | 8 +++++--- .../workbench/contrib/terminal/browser/terminalService.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index da54984afdc..d8b97df7808 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -258,7 +258,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { public constructor( private readonly _terminalFocusContextKey: IContextKey, private readonly _configHelper: TerminalConfigHelper, - private _container: HTMLElement, + private _container: HTMLElement | undefined, private _shellLaunchConfig: IShellLaunchConfig, @ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, @@ -548,7 +548,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } // The container changed, reattach - this._container.removeChild(this._wrapperElement); + if (this._container) { + this._container.removeChild(this._wrapperElement); + } this._container = container; this._container.appendChild(this._wrapperElement); } @@ -801,7 +803,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (this._wrapperElement.xterm) { this._wrapperElement.xterm = undefined; } - if (this._wrapperElement.parentElement) { + if (this._wrapperElement.parentElement && this._container) { this._container.removeChild(this._wrapperElement); } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 28d6d55692e..d635404778f 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; -import { IBrowserTerminalConfigHelper, ITerminalService, ITerminalInstance, ITerminalTab } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalService, ITerminalInstance, ITerminalTab } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; @@ -54,7 +54,7 @@ export class TerminalService implements ITerminalService { public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } public get terminalTabs(): ITerminalTab[] { return this._terminalTabs; } - private _configHelper: IBrowserTerminalConfigHelper; + private _configHelper: TerminalConfigHelper; private _terminalContainer: HTMLElement | undefined; public get configHelper(): ITerminalConfigHelper { return this._configHelper; } From 7f5a4a3f5bee5594ee31002d28a4d68c1a3bac78 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 4 Oct 2019 17:38:34 -0700 Subject: [PATCH 179/435] Fix strictFunctionTypes errors in terminal proxy Part of #81574 --- .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/common/extHostTerminalService.ts | 4 +-- .../api/node/extHostTerminalService.ts | 28 +++++++++++-------- .../contrib/terminal/browser/terminal.ts | 2 +- .../browser/terminalProcessExtHostProxy.ts | 2 +- .../terminal/browser/terminalService.ts | 2 +- .../contrib/terminal/common/terminal.ts | 2 +- 7 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7bd6aa6cb78..934d5f75b4e 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1189,7 +1189,7 @@ export interface ExtHostTerminalServiceShape { $acceptTerminalTitleChange(id: number, name: string): void; $acceptTerminalDimensions(id: number, cols: number, rows: number): void; $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void; - $spawnExtHostProcess(id: number, shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; + $spawnExtHostProcess(id: number, shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; $startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void; $acceptProcessInput(id: number, data: string): void; $acceptProcessResize(id: number, cols: number, rows: number): void; diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 368f057d8d8..c109ec77bf6 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -299,7 +299,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal; public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal; public abstract getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string; - public abstract $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise; + public abstract $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise; public abstract $requestAvailableShells(): Promise; public abstract $requestDefaultShellAndArgs(useAutomationShell: boolean): Promise; public abstract $acceptWorkspacePermissionsChanged(isAllowed: boolean): void; @@ -577,7 +577,7 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService { throw new Error('Not implemented'); } - public $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise { + public $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise { throw new Error('Not implemented'); } diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 13831193a59..1928820a110 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -123,7 +123,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider); } - public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise { + public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise { const shellLaunchConfig: IShellLaunchConfig = { name: shellLaunchConfigDto.name, executable: shellLaunchConfigDto.executable, @@ -155,17 +155,23 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { } } - const activeWorkspaceRootUri = URI.revive(activeWorkspaceRootUriComponents); - // Get the environment - const apiLastActiveWorkspace = await this._extHostWorkspace.getWorkspaceFolder(activeWorkspaceRootUri); - const lastActiveWorkspace = apiLastActiveWorkspace ? { - uri: apiLastActiveWorkspace.uri, - name: apiLastActiveWorkspace.name, - index: apiLastActiveWorkspace.index, - toResource: () => { - throw new Error('Not implemented'); + let lastActiveWorkspace: IWorkspaceFolder | null = null; + let activeWorkspaceRootUri: URI | undefined; + if (activeWorkspaceRootUriComponents) { + let activeWorkspaceRootUri = URI.revive(activeWorkspaceRootUriComponents); + // Get the environment + const apiLastActiveWorkspace = await this._extHostWorkspace.getWorkspaceFolder(activeWorkspaceRootUri); + if (apiLastActiveWorkspace) { + lastActiveWorkspace = { + uri: apiLastActiveWorkspace.uri, + name: apiLastActiveWorkspace.name, + index: apiLastActiveWorkspace.index, + toResource: () => { + throw new Error('Not implemented'); + } + }; } - } as IWorkspaceFolder : null; + } // Get the initial cwd const terminalConfig = configProvider.getConfiguration('terminal.integrated'); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index f2600039f97..25baad14130 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -145,7 +145,7 @@ export interface ITerminalService { preparePathForTerminalAsync(path: string, executable: string | undefined, title: string): Promise; extHostReady(remoteAuthority: string): void; - requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; + requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index 345840a6410..3db8f795da5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -48,7 +48,7 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal constructor( public terminalId: number, shellLaunchConfig: IShellLaunchConfig, - activeWorkspaceRootUri: URI, + activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, configHelper: ITerminalConfigHelper, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index d635404778f..a0772f91fd5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -135,7 +135,7 @@ export class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined); } - public requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void { + public requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void { this._extensionService.whenInstalledExtensionsRegistered().then(async () => { // Wait for the remoteAuthority to be ready (and listening for events) before firing // the event to spawn the ext host process diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index fbc3cc37ea7..444ac1b408f 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -341,7 +341,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable { export interface ISpawnExtHostProcessRequest { proxy: ITerminalProcessExtHostProxy; shellLaunchConfig: IShellLaunchConfig; - activeWorkspaceRootUri: URI; + activeWorkspaceRootUri: URI | undefined; cols: number; rows: number; isWorkspaceShellAllowed: boolean; From 36aa903d5a98ba5cf1d46b84c0a8fb3c2106bd8a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 17:15:11 -0700 Subject: [PATCH 180/435] Rewrite how we handle links in the md preview Try to simplify how we resolve links: - Move most logic out of the preview itself. - Simplify the amount of rewriting we do in the markdown engine --- .../markdown-language-features/media/index.js | 1012 +---------------- .../markdown-language-features/media/pre.js | 282 +---- .../markdown-language-features/package.json | 2 +- .../preview-src/index.ts | 34 +- .../src/features/preview.ts | 30 +- .../src/markdownEngine.ts | 57 +- .../src/util/links.ts | 26 +- 7 files changed, 96 insertions(+), 1347 deletions(-) diff --git a/extensions/markdown-language-features/media/index.js b/extensions/markdown-language-features/media/index.js index a17e886baff..666f4394dbb 100644 --- a/extensions/markdown-language-features/media/index.js +++ b/extensions/markdown-language-features/media/index.js @@ -1,1010 +1,2 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./preview-src/index.ts"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./node_modules/lodash.throttle/index.js": -/*!***********************************************!*\ - !*** ./node_modules/lodash.throttle/index.js ***! - \***********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {/** - * lodash (Custom Build) - * Build: `lodash modularize exports="npm" -o ./` - * Copyright jQuery Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ - -/** Used as the `TypeError` message for "Functions" methods. */ -var FUNC_ERROR_TEXT = 'Expected a function'; - -/** Used as references for various `Number` constants. */ -var NAN = 0 / 0; - -/** `Object#toString` result references. */ -var symbolTag = '[object Symbol]'; - -/** Used to match leading and trailing whitespace. */ -var reTrim = /^\s+|\s+$/g; - -/** Used to detect bad signed hexadecimal string values. */ -var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - -/** Used to detect binary string values. */ -var reIsBinary = /^0b[01]+$/i; - -/** Used to detect octal string values. */ -var reIsOctal = /^0o[0-7]+$/i; - -/** Built-in method references without a dependency on `root`. */ -var freeParseInt = parseInt; - -/** Detect free variable `global` from Node.js. */ -var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - -/** Detect free variable `self`. */ -var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - -/** Used as a reference to the global object. */ -var root = freeGlobal || freeSelf || Function('return this')(); - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var objectToString = objectProto.toString; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max, - nativeMin = Math.min; - -/** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ -var now = function() { - return root.Date.now(); -}; - -/** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. Subsequent - * calls to the debounced function return the result of the last `func` - * invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to debounce. - * @param {number} [wait=0] The number of milliseconds to delay. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=false] - * Specify invoking on the leading edge of the timeout. - * @param {number} [options.maxWait] - * The maximum time `func` is allowed to be delayed before it's invoked. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. - * @example - * - * // Avoid costly calculations while the window size is in flux. - * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); - * - * // Invoke `sendMail` when clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ -function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - result = wait - timeSinceLastCall; - - return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; -} - -/** - * Creates a throttled function that only invokes `func` at most once per - * every `wait` milliseconds. The throttled function comes with a `cancel` - * method to cancel delayed `func` invocations and a `flush` method to - * immediately invoke them. Provide `options` to indicate whether `func` - * should be invoked on the leading and/or trailing edge of the `wait` - * timeout. The `func` is invoked with the last arguments provided to the - * throttled function. Subsequent calls to the throttled function return the - * result of the last `func` invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the throttled function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.throttle` and `_.debounce`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to throttle. - * @param {number} [wait=0] The number of milliseconds to throttle invocations to. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=true] - * Specify invoking on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new throttled function. - * @example - * - * // Avoid excessively updating the position while scrolling. - * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); - * - * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. - * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); - * jQuery(element).on('click', throttled); - * - * // Cancel the trailing throttled invocation. - * jQuery(window).on('popstate', throttled.cancel); - */ -function throttle(func, wait, options) { - var leading = true, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - if (isObject(options)) { - leading = 'leading' in options ? !!options.leading : leading; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - return debounce(func, wait, { - 'leading': leading, - 'maxWait': wait, - 'trailing': trailing - }); -} - -/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ -function isObject(value) { - var type = typeof value; - return !!value && (type == 'object' || type == 'function'); -} - -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return !!value && typeof value == 'object'; -} - -/** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ -function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && objectToString.call(value) == symbolTag); -} - -/** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ -function toNumber(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = value.replace(reTrim, ''); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); -} - -module.exports = throttle; - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"))) - -/***/ }), - -/***/ "./node_modules/webpack/buildin/global.js": -/*!***********************************!*\ - !*** (webpack)/buildin/global.js ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -var g; - -// This works in non-strict mode -g = (function() { - return this; -})(); - -try { - // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1, eval)("this"); -} catch (e) { - // This works if the window reference is available - if (typeof window === "object") g = window; -} - -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} - -module.exports = g; - - -/***/ }), - -/***/ "./preview-src/activeLineMarker.ts": -/*!*****************************************!*\ - !*** ./preview-src/activeLineMarker.ts ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -const scroll_sync_1 = __webpack_require__(/*! ./scroll-sync */ "./preview-src/scroll-sync.ts"); -class ActiveLineMarker { - onDidChangeTextEditorSelection(line) { - const { previous } = scroll_sync_1.getElementsForSourceLine(line); - this._update(previous && previous.element); - } - _update(before) { - this._unmarkActiveElement(this._current); - this._markActiveElement(before); - this._current = before; - } - _unmarkActiveElement(element) { - if (!element) { - return; - } - element.className = element.className.replace(/\bcode-active-line\b/g, ''); - } - _markActiveElement(element) { - if (!element) { - return; - } - element.className += ' code-active-line'; - } -} -exports.ActiveLineMarker = ActiveLineMarker; - - -/***/ }), - -/***/ "./preview-src/events.ts": -/*!*******************************!*\ - !*** ./preview-src/events.ts ***! - \*******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -function onceDocumentLoaded(f) { - if (document.readyState === 'loading' || document.readyState === 'uninitialized') { - document.addEventListener('DOMContentLoaded', f); - } - else { - f(); - } -} -exports.onceDocumentLoaded = onceDocumentLoaded; - - -/***/ }), - -/***/ "./preview-src/index.ts": -/*!******************************!*\ - !*** ./preview-src/index.ts ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const activeLineMarker_1 = __webpack_require__(/*! ./activeLineMarker */ "./preview-src/activeLineMarker.ts"); -const events_1 = __webpack_require__(/*! ./events */ "./preview-src/events.ts"); -const messaging_1 = __webpack_require__(/*! ./messaging */ "./preview-src/messaging.ts"); -const scroll_sync_1 = __webpack_require__(/*! ./scroll-sync */ "./preview-src/scroll-sync.ts"); -const settings_1 = __webpack_require__(/*! ./settings */ "./preview-src/settings.ts"); -const throttle = __webpack_require__(/*! lodash.throttle */ "./node_modules/lodash.throttle/index.js"); -let scrollDisabled = true; -const marker = new activeLineMarker_1.ActiveLineMarker(); -const settings = settings_1.getSettings(); -const vscode = acquireVsCodeApi(); -// Set VS Code state -let state = settings_1.getData('data-state'); -vscode.setState(state); -const messaging = messaging_1.createPosterForVsCode(vscode); -window.cspAlerter.setPoster(messaging); -window.styleLoadingMonitor.setPoster(messaging); -window.onload = () => { - updateImageSizes(); -}; -events_1.onceDocumentLoaded(() => { - if (settings.scrollPreviewWithEditor) { - setTimeout(() => { - // Try to scroll to fragment if available - if (state.fragment) { - const element = scroll_sync_1.getLineElementForFragment(state.fragment); - if (element) { - scrollDisabled = true; - scroll_sync_1.scrollToRevealSourceLine(element.line); - } - } - else { - const initialLine = +settings.line; - if (!isNaN(initialLine)) { - scrollDisabled = true; - scroll_sync_1.scrollToRevealSourceLine(initialLine); - } - } - }, 0); - } -}); -const onUpdateView = (() => { - const doScroll = throttle((line) => { - scrollDisabled = true; - scroll_sync_1.scrollToRevealSourceLine(line); - }, 50); - return (line, settings) => { - if (!isNaN(line)) { - settings.line = line; - doScroll(line); - } - }; -})(); -let updateImageSizes = throttle(() => { - const imageInfo = []; - let images = document.getElementsByTagName('img'); - if (images) { - let i; - for (i = 0; i < images.length; i++) { - const img = images[i]; - if (img.classList.contains('loading')) { - img.classList.remove('loading'); - } - imageInfo.push({ - id: img.id, - height: img.height, - width: img.width - }); - } - messaging.postMessage('cacheImageSizes', imageInfo); - } -}, 50); -window.addEventListener('resize', () => { - scrollDisabled = true; - updateImageSizes(); -}, true); -window.addEventListener('message', event => { - if (event.data.source !== settings.source) { - return; - } - switch (event.data.type) { - case 'onDidChangeTextEditorSelection': - marker.onDidChangeTextEditorSelection(event.data.line); - break; - case 'updateView': - onUpdateView(event.data.line, settings); - break; - } -}, false); -document.addEventListener('dblclick', event => { - if (!settings.doubleClickToSwitchToEditor) { - return; - } - // Ignore clicks on links - for (let node = event.target; node; node = node.parentNode) { - if (node.tagName === 'A') { - return; - } - } - const offset = event.pageY; - const line = scroll_sync_1.getEditorLineNumberForPageOffset(offset); - if (typeof line === 'number' && !isNaN(line)) { - messaging.postMessage('didClick', { line: Math.floor(line) }); - } -}); -document.addEventListener('click', event => { - if (!event) { - return; - } - let node = event.target; - while (node) { - if (node.tagName && node.tagName === 'A' && node.href) { - if (node.getAttribute('href').startsWith('#')) { - break; - } - if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { - const [path, fragment] = node.href - .replace(/^file:\/\//i, '') - .replace(/^vscode-resource:\/\/[^\/]+\//i, '') - .replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)) - .split('#'); - messaging.postMessage('clickLink', { path, fragment }); - event.preventDefault(); - event.stopPropagation(); - break; - } - break; - } - node = node.parentNode; - } -}, true); -window.addEventListener('scroll', throttle(() => { - if (scrollDisabled) { - scrollDisabled = false; - } - else { - const line = scroll_sync_1.getEditorLineNumberForPageOffset(window.scrollY); - if (typeof line === 'number' && !isNaN(line)) { - messaging.postMessage('revealLine', { line }); - state.line = line; - vscode.setState(state); - } - } -}, 50)); -function escapeRegExp(text) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); -} - - -/***/ }), - -/***/ "./preview-src/messaging.ts": -/*!**********************************!*\ - !*** ./preview-src/messaging.ts ***! - \**********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const settings_1 = __webpack_require__(/*! ./settings */ "./preview-src/settings.ts"); -exports.createPosterForVsCode = (vscode) => { - return new class { - postMessage(type, body) { - vscode.postMessage({ - type, - source: settings_1.getSettings().source, - body - }); - } - }; -}; - - -/***/ }), - -/***/ "./preview-src/scroll-sync.ts": -/*!************************************!*\ - !*** ./preview-src/scroll-sync.ts ***! - \************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const settings_1 = __webpack_require__(/*! ./settings */ "./preview-src/settings.ts"); -function clamp(min, max, value) { - return Math.min(max, Math.max(min, value)); -} -function clampLine(line) { - return clamp(0, settings_1.getSettings().lineCount - 1, line); -} -const getCodeLineElements = (() => { - let elements; - return () => { - if (!elements) { - elements = [{ element: document.body, line: 0 }]; - for (const element of document.getElementsByClassName('code-line')) { - const line = +element.getAttribute('data-line'); - if (!isNaN(line)) { - elements.push({ element: element, line }); - } - } - } - return elements; - }; -})(); -/** - * Find the html elements that map to a specific target line in the editor. - * - * If an exact match, returns a single element. If the line is between elements, - * returns the element prior to and the element after the given line. - */ -function getElementsForSourceLine(targetLine) { - const lineNumber = Math.floor(targetLine); - const lines = getCodeLineElements(); - let previous = lines[0] || null; - for (const entry of lines) { - if (entry.line === lineNumber) { - return { previous: entry, next: undefined }; - } - else if (entry.line > lineNumber) { - return { previous, next: entry }; - } - previous = entry; - } - return { previous }; -} -exports.getElementsForSourceLine = getElementsForSourceLine; -/** - * Find the html elements that are at a specific pixel offset on the page. - */ -function getLineElementsAtPageOffset(offset) { - const lines = getCodeLineElements(); - const position = offset - window.scrollY; - let lo = -1; - let hi = lines.length - 1; - while (lo + 1 < hi) { - const mid = Math.floor((lo + hi) / 2); - const bounds = lines[mid].element.getBoundingClientRect(); - if (bounds.top + bounds.height >= position) { - hi = mid; - } - else { - lo = mid; - } - } - const hiElement = lines[hi]; - const hiBounds = hiElement.element.getBoundingClientRect(); - if (hi >= 1 && hiBounds.top > position) { - const loElement = lines[lo]; - return { previous: loElement, next: hiElement }; - } - return { previous: hiElement }; -} -exports.getLineElementsAtPageOffset = getLineElementsAtPageOffset; -/** - * Attempt to reveal the element for a source line in the editor. - */ -function scrollToRevealSourceLine(line) { - if (!settings_1.getSettings().scrollPreviewWithEditor) { - return; - } - if (line <= 0) { - window.scroll(window.scrollX, 0); - return; - } - const { previous, next } = getElementsForSourceLine(line); - if (!previous) { - return; - } - let scrollTo = 0; - const rect = previous.element.getBoundingClientRect(); - const previousTop = rect.top; - if (next && next.line !== previous.line) { - // Between two elements. Go to percentage offset between them. - const betweenProgress = (line - previous.line) / (next.line - previous.line); - const elementOffset = next.element.getBoundingClientRect().top - previousTop; - scrollTo = previousTop + betweenProgress * elementOffset; - } - else { - const progressInElement = line - Math.floor(line); - scrollTo = previousTop + (rect.height * progressInElement); - } - window.scroll(window.scrollX, Math.max(1, window.scrollY + scrollTo)); -} -exports.scrollToRevealSourceLine = scrollToRevealSourceLine; -function getEditorLineNumberForPageOffset(offset) { - const { previous, next } = getLineElementsAtPageOffset(offset); - if (previous) { - const previousBounds = previous.element.getBoundingClientRect(); - const offsetFromPrevious = (offset - window.scrollY - previousBounds.top); - if (next) { - const progressBetweenElements = offsetFromPrevious / (next.element.getBoundingClientRect().top - previousBounds.top); - const line = previous.line + progressBetweenElements * (next.line - previous.line); - return clampLine(line); - } - else { - const progressWithinElement = offsetFromPrevious / (previousBounds.height); - const line = previous.line + progressWithinElement; - return clampLine(line); - } - } - return null; -} -exports.getEditorLineNumberForPageOffset = getEditorLineNumberForPageOffset; -/** - * Try to find the html element by using a fragment id - */ -function getLineElementForFragment(fragment) { - return getCodeLineElements().find((element) => { - return element.element.id === fragment; - }); -} -exports.getLineElementForFragment = getLineElementForFragment; - - -/***/ }), - -/***/ "./preview-src/settings.ts": -/*!*********************************!*\ - !*** ./preview-src/settings.ts ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -let cachedSettings = undefined; -function getData(key) { - const element = document.getElementById('vscode-markdown-preview-data'); - if (element) { - const data = element.getAttribute(key); - if (data) { - return JSON.parse(data); - } - } - throw new Error(`Could not load data for ${key}`); -} -exports.getData = getData; -function getSettings() { - if (cachedSettings) { - return cachedSettings; - } - cachedSettings = getData('data-settings'); - if (cachedSettings) { - return cachedSettings; - } - throw new Error('Could not load settings'); -} -exports.getSettings = getSettings; - - -/***/ }) - -/******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsTUFBTTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx5QkFBeUI7QUFDcEU7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QywyQ0FBMkM7QUFDdkY7QUFDQSxvREFBb0QsaUJBQWlCO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsT0FBTztBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBLGdDQUFnQztBQUNoQzs7Ozs7Ozs7Ozs7OztBQ3ZKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsa0NBQWtDO0FBQzNEO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyx5QkFBeUI7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxpQkFBaUI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsaUJBQWlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7Ozs7Ozs7Ozs7OztBQ3ZJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLElBQUk7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9wcmV2aWV3LXNyYy9pbmRleC50c1wiKTtcbiIsIi8qKlxuICogbG9kYXNoIChDdXN0b20gQnVpbGQpIDxodHRwczovL2xvZGFzaC5jb20vPlxuICogQnVpbGQ6IGBsb2Rhc2ggbW9kdWxhcml6ZSBleHBvcnRzPVwibnBtXCIgLW8gLi9gXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyA8aHR0cHM6Ly9qcXVlcnkub3JnLz5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbiAqL1xuXG4vKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG52YXIgTkFOID0gMCAvIDA7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxuLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbnZhciByZVRyaW0gPSAvXlxccyt8XFxzKyQvZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJhZCBzaWduZWQgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiaW5hcnkgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmluYXJ5ID0gL14wYlswMV0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzT2N0YWwgPSAvXjBvWzAtN10rJC9pO1xuXG4vKiogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgd2l0aG91dCBhIGRlcGVuZGVuY3kgb24gYHJvb3RgLiAqL1xudmFyIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xudmFyIGZyZWVTZWxmID0gdHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZiAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHNlbGY7XG5cbi8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xudmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZVxuICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gKiBvZiB2YWx1ZXMuXG4gKi9cbnZhciBvYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgbmF0aXZlTWluID0gTWF0aC5taW47XG5cbi8qKlxuICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDIuNC4wXG4gKiBAY2F0ZWdvcnkgRGF0ZVxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gKiB9LCBfLm5vdygpKTtcbiAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gKi9cbnZhciBub3cgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHJvb3QuRGF0ZS5ub3coKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gKiBtaWxsaXNlY29uZHMgaGF2ZSBlbGFwc2VkIHNpbmNlIHRoZSBsYXN0IHRpbWUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiB3YXNcbiAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICogUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb24gdGhlXG4gKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gKiBjYWxscyB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYFxuICogaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5LlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm1heFdhaXRdXG4gKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdyZXNpemUnLCBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSk7XG4gKlxuICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5kZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAqIH0pKTtcbiAqXG4gKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICogdmFyIGRlYm91bmNlZCA9IF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwgeyAnbWF4V2FpdCc6IDEwMDAgfSk7XG4gKiB2YXIgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJyk7XG4gKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyBkZWJvdW5jZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsYXN0QXJncyxcbiAgICAgIGxhc3RUaGlzLFxuICAgICAgbWF4V2FpdCxcbiAgICAgIHJlc3VsdCxcbiAgICAgIHRpbWVySWQsXG4gICAgICBsYXN0Q2FsbFRpbWUsXG4gICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICBsZWFkaW5nID0gZmFsc2UsXG4gICAgICBtYXhpbmcgPSBmYWxzZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB3YWl0ID0gdG9OdW1iZXIod2FpdCkgfHwgMDtcbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgIG1heGluZyA9ICdtYXhXYWl0JyBpbiBvcHRpb25zO1xuICAgIG1heFdhaXQgPSBtYXhpbmcgPyBuYXRpdmVNYXgodG9OdW1iZXIob3B0aW9ucy5tYXhXYWl0KSB8fCAwLCB3YWl0KSA6IG1heFdhaXQ7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuXG4gIGZ1bmN0aW9uIGludm9rZUZ1bmModGltZSkge1xuICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgIHRoaXNBcmcgPSBsYXN0VGhpcztcblxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxlYWRpbmdFZGdlKHRpbWUpIHtcbiAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAvLyBTdGFydCB0aGUgdGltZXIgZm9yIHRoZSB0cmFpbGluZyBlZGdlLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgcmV0dXJuIGxlYWRpbmcgPyBpbnZva2VGdW5jKHRpbWUpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZSxcbiAgICAgICAgcmVzdWx0ID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgcmV0dXJuIG1heGluZyA/IG5hdGl2ZU1pbihyZXN1bHQsIG1heFdhaXQgLSB0aW1lU2luY2VMYXN0SW52b2tlKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZTtcblxuICAgIC8vIEVpdGhlciB0aGlzIGlzIHRoZSBmaXJzdCBjYWxsLCBhY3Rpdml0eSBoYXMgc3RvcHBlZCBhbmQgd2UncmUgYXQgdGhlXG4gICAgLy8gdHJhaWxpbmcgZWRnZSwgdGhlIHN5c3RlbSB0aW1lIGhhcyBnb25lIGJhY2t3YXJkcyBhbmQgd2UncmUgdHJlYXRpbmdcbiAgICAvLyBpdCBhcyB0aGUgdHJhaWxpbmcgZWRnZSwgb3Igd2UndmUgaGl0IHRoZSBgbWF4V2FpdGAgbGltaXQuXG4gICAgcmV0dXJuIChsYXN0Q2FsbFRpbWUgPT09IHVuZGVmaW5lZCB8fCAodGltZVNpbmNlTGFzdENhbGwgPj0gd2FpdCkgfHxcbiAgICAgICh0aW1lU2luY2VMYXN0Q2FsbCA8IDApIHx8IChtYXhpbmcgJiYgdGltZVNpbmNlTGFzdEludm9rZSA+PSBtYXhXYWl0KSk7XG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKTtcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpO1xuICAgIH1cbiAgICAvLyBSZXN0YXJ0IHRoZSB0aW1lci5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHJlbWFpbmluZ1dhaXQodGltZSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gT25seSBpbnZva2UgaWYgd2UgaGF2ZSBgbGFzdEFyZ3NgIHdoaWNoIG1lYW5zIGBmdW5jYCBoYXMgYmVlblxuICAgIC8vIGRlYm91bmNlZCBhdCBsZWFzdCBvbmNlLlxuICAgIGlmICh0cmFpbGluZyAmJiBsYXN0QXJncykge1xuICAgICAgcmV0dXJuIGludm9rZUZ1bmModGltZSk7XG4gICAgfVxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfVxuICAgIGxhc3RJbnZva2VUaW1lID0gMDtcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgIHJldHVybiB0aW1lcklkID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiB0cmFpbGluZ0VkZ2Uobm93KCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCksXG4gICAgICAgIGlzSW52b2tpbmcgPSBzaG91bGRJbnZva2UodGltZSk7XG5cbiAgICBsYXN0QXJncyA9IGFyZ3VtZW50cztcbiAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgbGFzdENhbGxUaW1lID0gdGltZTtcblxuICAgIGlmIChpc0ludm9raW5nKSB7XG4gICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBsZWFkaW5nRWRnZShsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICByZXR1cm4gaW52b2tlRnVuYyhsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gIGRlYm91bmNlZC5mbHVzaCA9IGZsdXNoO1xuICByZXR1cm4gZGVib3VuY2VkO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAqIGV2ZXJ5IGB3YWl0YCBtaWxsaXNlY29uZHMuIFRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgXG4gKiBtZXRob2QgdG8gY2FuY2VsIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvXG4gKiBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS4gUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2BcbiAqIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGBcbiAqIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZCB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGVcbiAqIHRocm90dGxlZCBmdW5jdGlvbi4gU3Vic2VxdWVudCBjYWxscyB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHJldHVybiB0aGVcbiAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRocm90dGxlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy50aHJvdHRsZWAgYW5kIGBfLmRlYm91bmNlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHRocm90dGxlIGludm9jYXRpb25zIHRvLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHRocm90dGxlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgZXhjZXNzaXZlbHkgdXBkYXRpbmcgdGhlIHBvc2l0aW9uIHdoaWxlIHNjcm9sbGluZy5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdzY3JvbGwnLCBfLnRocm90dGxlKHVwZGF0ZVBvc2l0aW9uLCAxMDApKTtcbiAqXG4gKiAvLyBJbnZva2UgYHJlbmV3VG9rZW5gIHdoZW4gdGhlIGNsaWNrIGV2ZW50IGlzIGZpcmVkLCBidXQgbm90IG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IDUgbWludXRlcy5cbiAqIHZhciB0aHJvdHRsZWQgPSBfLnRocm90dGxlKHJlbmV3VG9rZW4sIDMwMDAwMCwgeyAndHJhaWxpbmcnOiBmYWxzZSB9KTtcbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCB0aHJvdHRsZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgdGhyb3R0bGVkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCB0aHJvdHRsZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cbiAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHtcbiAgICAnbGVhZGluZyc6IGxlYWRpbmcsXG4gICAgJ21heFdhaXQnOiB3YWl0LFxuICAgICd0cmFpbGluZyc6IHRyYWlsaW5nXG4gIH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHN5bWJvbFRhZyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIG51bWJlci5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAqIEBleGFtcGxlXG4gKlxuICogXy50b051bWJlcigzLjIpO1xuICogLy8gPT4gMy4yXG4gKlxuICogXy50b051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAqIC8vID0+IDVlLTMyNFxuICpcbiAqIF8udG9OdW1iZXIoSW5maW5pdHkpO1xuICogLy8gPT4gSW5maW5pdHlcbiAqXG4gKiBfLnRvTnVtYmVyKCczLjInKTtcbiAqIC8vID0+IDMuMlxuICovXG5mdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gTkFOO1xuICB9XG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICB2YXIgb3RoZXIgPSB0eXBlb2YgdmFsdWUudmFsdWVPZiA9PSAnZnVuY3Rpb24nID8gdmFsdWUudmFsdWVPZigpIDogdmFsdWU7XG4gICAgdmFsdWUgPSBpc09iamVjdChvdGhlcikgPyAob3RoZXIgKyAnJykgOiBvdGhlcjtcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiArdmFsdWU7XG4gIH1cbiAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICB2YXIgaXNCaW5hcnkgPSByZUlzQmluYXJ5LnRlc3QodmFsdWUpO1xuICByZXR1cm4gKGlzQmluYXJ5IHx8IHJlSXNPY3RhbC50ZXN0KHZhbHVlKSlcbiAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICA6IChyZUlzQmFkSGV4LnRlc3QodmFsdWUpID8gTkFOIDogK3ZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0aHJvdHRsZTtcbiIsInZhciBnO1xyXG5cclxuLy8gVGhpcyB3b3JrcyBpbiBub24tc3RyaWN0IG1vZGVcclxuZyA9IChmdW5jdGlvbigpIHtcclxuXHRyZXR1cm4gdGhpcztcclxufSkoKTtcclxuXHJcbnRyeSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiBldmFsIGlzIGFsbG93ZWQgKHNlZSBDU1ApXHJcblx0ZyA9IGcgfHwgRnVuY3Rpb24oXCJyZXR1cm4gdGhpc1wiKSgpIHx8ICgxLCBldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2ggKGUpIHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIHRoZSB3aW5kb3cgcmVmZXJlbmNlIGlzIGF2YWlsYWJsZVxyXG5cdGlmICh0eXBlb2Ygd2luZG93ID09PSBcIm9iamVjdFwiKSBnID0gd2luZG93O1xyXG59XHJcblxyXG4vLyBnIGNhbiBzdGlsbCBiZSB1bmRlZmluZWQsIGJ1dCBub3RoaW5nIHRvIGRvIGFib3V0IGl0Li4uXHJcbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXHJcbi8vIGVhc2llciB0byBoYW5kbGUgdGhpcyBjYXNlLiBpZighZ2xvYmFsKSB7IC4uLn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZztcclxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmNvbnN0IHNjcm9sbF9zeW5jXzEgPSByZXF1aXJlKFwiLi9zY3JvbGwtc3luY1wiKTtcbmNsYXNzIEFjdGl2ZUxpbmVNYXJrZXIge1xuICAgIG9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihsaW5lKSB7XG4gICAgICAgIGNvbnN0IHsgcHJldmlvdXMgfSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKGxpbmUpO1xuICAgICAgICB0aGlzLl91cGRhdGUocHJldmlvdXMgJiYgcHJldmlvdXMuZWxlbWVudCk7XG4gICAgfVxuICAgIF91cGRhdGUoYmVmb3JlKSB7XG4gICAgICAgIHRoaXMuX3VubWFya0FjdGl2ZUVsZW1lbnQodGhpcy5fY3VycmVudCk7XG4gICAgICAgIHRoaXMuX21hcmtBY3RpdmVFbGVtZW50KGJlZm9yZSk7XG4gICAgICAgIHRoaXMuX2N1cnJlbnQgPSBiZWZvcmU7XG4gICAgfVxuICAgIF91bm1hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50LmNsYXNzTmFtZS5yZXBsYWNlKC9cXGJjb2RlLWFjdGl2ZS1saW5lXFxiL2csICcnKTtcbiAgICB9XG4gICAgX21hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgKz0gJyBjb2RlLWFjdGl2ZS1saW5lJztcbiAgICB9XG59XG5leHBvcnRzLkFjdGl2ZUxpbmVNYXJrZXIgPSBBY3RpdmVMaW5lTWFya2VyO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmZ1bmN0aW9uIG9uY2VEb2N1bWVudExvYWRlZChmKSB7XG4gICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGYpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZigpO1xuICAgIH1cbn1cbmV4cG9ydHMub25jZURvY3VtZW50TG9hZGVkID0gb25jZURvY3VtZW50TG9hZGVkO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGFjdGl2ZUxpbmVNYXJrZXJfMSA9IHJlcXVpcmUoXCIuL2FjdGl2ZUxpbmVNYXJrZXJcIik7XG5jb25zdCBldmVudHNfMSA9IHJlcXVpcmUoXCIuL2V2ZW50c1wiKTtcbmNvbnN0IG1lc3NhZ2luZ18xID0gcmVxdWlyZShcIi4vbWVzc2FnaW5nXCIpO1xuY29uc3Qgc2Nyb2xsX3N5bmNfMSA9IHJlcXVpcmUoXCIuL3Njcm9sbC1zeW5jXCIpO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuY29uc3QgdGhyb3R0bGUgPSByZXF1aXJlKFwibG9kYXNoLnRocm90dGxlXCIpO1xubGV0IHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbmNvbnN0IG1hcmtlciA9IG5ldyBhY3RpdmVMaW5lTWFya2VyXzEuQWN0aXZlTGluZU1hcmtlcigpO1xuY29uc3Qgc2V0dGluZ3MgPSBzZXR0aW5nc18xLmdldFNldHRpbmdzKCk7XG5jb25zdCB2c2NvZGUgPSBhY3F1aXJlVnNDb2RlQXBpKCk7XG4vLyBTZXQgVlMgQ29kZSBzdGF0ZVxubGV0IHN0YXRlID0gc2V0dGluZ3NfMS5nZXREYXRhKCdkYXRhLXN0YXRlJyk7XG52c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuY29uc3QgbWVzc2FnaW5nID0gbWVzc2FnaW5nXzEuY3JlYXRlUG9zdGVyRm9yVnNDb2RlKHZzY29kZSk7XG53aW5kb3cuY3NwQWxlcnRlci5zZXRQb3N0ZXIobWVzc2FnaW5nKTtcbndpbmRvdy5zdHlsZUxvYWRpbmdNb25pdG9yLnNldFBvc3RlcihtZXNzYWdpbmcpO1xud2luZG93Lm9ubG9hZCA9ICgpID0+IHtcbiAgICB1cGRhdGVJbWFnZVNpemVzKCk7XG59O1xuZXZlbnRzXzEub25jZURvY3VtZW50TG9hZGVkKCgpID0+IHtcbiAgICBpZiAoc2V0dGluZ3Muc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAvLyBUcnkgdG8gc2Nyb2xsIHRvIGZyYWdtZW50IGlmIGF2YWlsYWJsZVxuICAgICAgICAgICAgaWYgKHN0YXRlLmZyYWdtZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHNjcm9sbF9zeW5jXzEuZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudChzdGF0ZS5mcmFnbWVudCk7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShlbGVtZW50LmxpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluaXRpYWxMaW5lID0gK3NldHRpbmdzLmxpbmU7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihpbml0aWFsTGluZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxfc3luY18xLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShpbml0aWFsTGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICB9XG59KTtcbmNvbnN0IG9uVXBkYXRlVmlldyA9ICgoKSA9PiB7XG4gICAgY29uc3QgZG9TY3JvbGwgPSB0aHJvdHRsZSgobGluZSkgPT4ge1xuICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGxpbmUpO1xuICAgIH0sIDUwKTtcbiAgICByZXR1cm4gKGxpbmUsIHNldHRpbmdzKSA9PiB7XG4gICAgICAgIGlmICghaXNOYU4obGluZSkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmxpbmUgPSBsaW5lO1xuICAgICAgICAgICAgZG9TY3JvbGwobGluZSk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcbmxldCB1cGRhdGVJbWFnZVNpemVzID0gdGhyb3R0bGUoKCkgPT4ge1xuICAgIGNvbnN0IGltYWdlSW5mbyA9IFtdO1xuICAgIGxldCBpbWFnZXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaW1nJyk7XG4gICAgaWYgKGltYWdlcykge1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGltYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgaW1nID0gaW1hZ2VzW2ldO1xuICAgICAgICAgICAgaWYgKGltZy5jbGFzc0xpc3QuY29udGFpbnMoJ2xvYWRpbmcnKSkge1xuICAgICAgICAgICAgICAgIGltZy5jbGFzc0xpc3QucmVtb3ZlKCdsb2FkaW5nJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbWFnZUluZm8ucHVzaCh7XG4gICAgICAgICAgICAgICAgaWQ6IGltZy5pZCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGltZy5oZWlnaHQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGltZy53aWR0aFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjYWNoZUltYWdlU2l6ZXMnLCBpbWFnZUluZm8pO1xuICAgIH1cbn0sIDUwKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCAoKSA9PiB7XG4gICAgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuICAgIHVwZGF0ZUltYWdlU2l6ZXMoKTtcbn0sIHRydWUpO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBldmVudCA9PiB7XG4gICAgaWYgKGV2ZW50LmRhdGEuc291cmNlICE9PSBzZXR0aW5ncy5zb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzd2l0Y2ggKGV2ZW50LmRhdGEudHlwZSkge1xuICAgICAgICBjYXNlICdvbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24nOlxuICAgICAgICAgICAgbWFya2VyLm9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihldmVudC5kYXRhLmxpbmUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3VwZGF0ZVZpZXcnOlxuICAgICAgICAgICAgb25VcGRhdGVWaWV3KGV2ZW50LmRhdGEubGluZSwgc2V0dGluZ3MpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufSwgZmFsc2UpO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBldmVudCA9PiB7XG4gICAgaWYgKCFzZXR0aW5ncy5kb3VibGVDbGlja1RvU3dpdGNoVG9FZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBJZ25vcmUgY2xpY2tzIG9uIGxpbmtzXG4gICAgZm9yIChsZXQgbm9kZSA9IGV2ZW50LnRhcmdldDsgbm9kZTsgbm9kZSA9IG5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICBpZiAobm9kZS50YWdOYW1lID09PSAnQScpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBvZmZzZXQgPSBldmVudC5wYWdlWTtcbiAgICBjb25zdCBsaW5lID0gc2Nyb2xsX3N5bmNfMS5nZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldChvZmZzZXQpO1xuICAgIGlmICh0eXBlb2YgbGluZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnZGlkQ2xpY2snLCB7IGxpbmU6IE1hdGguZmxvb3IobGluZSkgfSk7XG4gICAgfVxufSk7XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGV2ZW50ID0+IHtcbiAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IG5vZGUgPSBldmVudC50YXJnZXQ7XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUudGFnTmFtZSAmJiBub2RlLnRhZ05hbWUgPT09ICdBJyAmJiBub2RlLmhyZWYpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUuaHJlZi5zdGFydHNXaXRoKCdmaWxlOi8vJykgfHwgbm9kZS5ocmVmLnN0YXJ0c1dpdGgoJ3ZzY29kZS1yZXNvdXJjZTonKSB8fCBub2RlLmhyZWYuc3RhcnRzV2l0aChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtwYXRoLCBmcmFnbWVudF0gPSBub2RlLmhyZWZcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL15maWxlOlxcL1xcLy9pLCAnJylcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL152c2NvZGUtcmVzb3VyY2U6XFwvXFwvW15cXC9dK1xcLy9pLCAnJylcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UobmV3IFJlZ0V4cChgXiR7ZXNjYXBlUmVnRXhwKHNldHRpbmdzLndlYnZpZXdSZXNvdXJjZVJvb3QpfWApKVxuICAgICAgICAgICAgICAgICAgICAuc3BsaXQoJyMnKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NsaWNrTGluaycsIHsgcGF0aCwgZnJhZ21lbnQgfSk7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgfVxufSwgdHJ1ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhyb3R0bGUoKCkgPT4ge1xuICAgIGlmIChzY3JvbGxEaXNhYmxlZCkge1xuICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuICAgICAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdyZXZlYWxMaW5lJywgeyBsaW5lIH0pO1xuICAgICAgICAgICAgc3RhdGUubGluZSA9IGxpbmU7XG4gICAgICAgICAgICB2c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxufSwgNTApKTtcbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKTtcbn1cbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5leHBvcnRzLmNyZWF0ZVBvc3RlckZvclZzQ29kZSA9ICh2c2NvZGUpID0+IHtcbiAgICByZXR1cm4gbmV3IGNsYXNzIHtcbiAgICAgICAgcG9zdE1lc3NhZ2UodHlwZSwgYm9keSkge1xuICAgICAgICAgICAgdnNjb2RlLnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgIHNvdXJjZTogc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNvdXJjZSxcbiAgICAgICAgICAgICAgICBib2R5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmZ1bmN0aW9uIGNsYW1wKG1pbiwgbWF4LCB2YWx1ZSkge1xuICAgIHJldHVybiBNYXRoLm1pbihtYXgsIE1hdGgubWF4KG1pbiwgdmFsdWUpKTtcbn1cbmZ1bmN0aW9uIGNsYW1wTGluZShsaW5lKSB7XG4gICAgcmV0dXJuIGNsYW1wKDAsIHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKS5saW5lQ291bnQgLSAxLCBsaW5lKTtcbn1cbmNvbnN0IGdldENvZGVMaW5lRWxlbWVudHMgPSAoKCkgPT4ge1xuICAgIGxldCBlbGVtZW50cztcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAoIWVsZW1lbnRzKSB7XG4gICAgICAgICAgICBlbGVtZW50cyA9IFt7IGVsZW1lbnQ6IGRvY3VtZW50LmJvZHksIGxpbmU6IDAgfV07XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS1saW5lJykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsaW5lID0gK2VsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWxpbmUnKTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTmFOKGxpbmUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzLnB1c2goeyBlbGVtZW50OiBlbGVtZW50LCBsaW5lIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgfTtcbn0pKCk7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBtYXAgdG8gYSBzcGVjaWZpYyB0YXJnZXQgbGluZSBpbiB0aGUgZWRpdG9yLlxuICpcbiAqIElmIGFuIGV4YWN0IG1hdGNoLCByZXR1cm5zIGEgc2luZ2xlIGVsZW1lbnQuIElmIHRoZSBsaW5lIGlzIGJldHdlZW4gZWxlbWVudHMsXG4gKiByZXR1cm5zIHRoZSBlbGVtZW50IHByaW9yIHRvIGFuZCB0aGUgZWxlbWVudCBhZnRlciB0aGUgZ2l2ZW4gbGluZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKHRhcmdldExpbmUpIHtcbiAgICBjb25zdCBsaW5lTnVtYmVyID0gTWF0aC5mbG9vcih0YXJnZXRMaW5lKTtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBsZXQgcHJldmlvdXMgPSBsaW5lc1swXSB8fCBudWxsO1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgbGluZXMpIHtcbiAgICAgICAgaWYgKGVudHJ5LmxpbmUgPT09IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzOiBlbnRyeSwgbmV4dDogdW5kZWZpbmVkIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZW50cnkubGluZSA+IGxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHByZXZpb3VzLCBuZXh0OiBlbnRyeSB9O1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzID0gZW50cnk7XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzIH07XG59XG5leHBvcnRzLmdldEVsZW1lbnRzRm9yU291cmNlTGluZSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZTtcbi8qKlxuICogRmluZCB0aGUgaHRtbCBlbGVtZW50cyB0aGF0IGFyZSBhdCBhIHNwZWNpZmljIHBpeGVsIG9mZnNldCBvbiB0aGUgcGFnZS5cbiAqL1xuZnVuY3Rpb24gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IGxpbmVzID0gZ2V0Q29kZUxpbmVFbGVtZW50cygpO1xuICAgIGNvbnN0IHBvc2l0aW9uID0gb2Zmc2V0IC0gd2luZG93LnNjcm9sbFk7XG4gICAgbGV0IGxvID0gLTE7XG4gICAgbGV0IGhpID0gbGluZXMubGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAobG8gKyAxIDwgaGkpIHtcbiAgICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG8gKyBoaSkgLyAyKTtcbiAgICAgICAgY29uc3QgYm91bmRzID0gbGluZXNbbWlkXS5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBpZiAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgPj0gcG9zaXRpb24pIHtcbiAgICAgICAgICAgIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG8gPSBtaWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaGlFbGVtZW50ID0gbGluZXNbaGldO1xuICAgIGNvbnN0IGhpQm91bmRzID0gaGlFbGVtZW50LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgaWYgKGhpID49IDEgJiYgaGlCb3VuZHMudG9wID4gcG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgbG9FbGVtZW50ID0gbGluZXNbbG9dO1xuICAgICAgICByZXR1cm4geyBwcmV2aW91czogbG9FbGVtZW50LCBuZXh0OiBoaUVsZW1lbnQgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcHJldmlvdXM6IGhpRWxlbWVudCB9O1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQgPSBnZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQ7XG4vKipcbiAqIEF0dGVtcHQgdG8gcmV2ZWFsIHRoZSBlbGVtZW50IGZvciBhIHNvdXJjZSBsaW5lIGluIHRoZSBlZGl0b3IuXG4gKi9cbmZ1bmN0aW9uIHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKSB7XG4gICAgaWYgKCFzZXR0aW5nc18xLmdldFNldHRpbmdzKCkuc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobGluZSA8PSAwKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcbiAgICBpZiAoIXByZXZpb3VzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHNjcm9sbFRvID0gMDtcbiAgICBjb25zdCByZWN0ID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBwcmV2aW91c1RvcCA9IHJlY3QudG9wO1xuICAgIGlmIChuZXh0ICYmIG5leHQubGluZSAhPT0gcHJldmlvdXMubGluZSkge1xuICAgICAgICAvLyBCZXR3ZWVuIHR3byBlbGVtZW50cy4gR28gdG8gcGVyY2VudGFnZSBvZmZzZXQgYmV0d2VlbiB0aGVtLlxuICAgICAgICBjb25zdCBiZXR3ZWVuUHJvZ3Jlc3MgPSAobGluZSAtIHByZXZpb3VzLmxpbmUpIC8gKG5leHQubGluZSAtIHByZXZpb3VzLmxpbmUpO1xuICAgICAgICBjb25zdCBlbGVtZW50T2Zmc2V0ID0gbmV4dC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtIHByZXZpb3VzVG9wO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgYmV0d2VlblByb2dyZXNzICogZWxlbWVudE9mZnNldDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IHByb2dyZXNzSW5FbGVtZW50ID0gbGluZSAtIE1hdGguZmxvb3IobGluZSk7XG4gICAgICAgIHNjcm9sbFRvID0gcHJldmlvdXNUb3AgKyAocmVjdC5oZWlnaHQgKiBwcm9ncmVzc0luRWxlbWVudCk7XG4gICAgfVxuICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnNjcm9sbFgsIE1hdGgubWF4KDEsIHdpbmRvdy5zY3JvbGxZICsgc2Nyb2xsVG8pKTtcbn1cbmV4cG9ydHMuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lID0gc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lO1xuZnVuY3Rpb24gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KSB7XG4gICAgY29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCk7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzQm91bmRzID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0RnJvbVByZXZpb3VzID0gKG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgaWYgKG5leHQpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb2dyZXNzQmV0d2VlbkVsZW1lbnRzID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c0JvdW5kcy50b3ApO1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IHByZXZpb3VzLmxpbmUgKyBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyAqIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc1dpdGhpbkVsZW1lbnQgPSBvZmZzZXRGcm9tUHJldmlvdXMgLyAocHJldmlvdXNCb3VuZHMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50O1xuICAgICAgICAgICAgcmV0dXJuIGNsYW1wTGluZShsaW5lKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmV4cG9ydHMuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQgPSBnZXRFZGl0b3JMaW5lTnVtYmVyRm9yUGFnZU9mZnNldDtcbi8qKlxuICogVHJ5IHRvIGZpbmQgdGhlIGh0bWwgZWxlbWVudCBieSB1c2luZyBhIGZyYWdtZW50IGlkXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQoZnJhZ21lbnQpIHtcbiAgICByZXR1cm4gZ2V0Q29kZUxpbmVFbGVtZW50cygpLmZpbmQoKGVsZW1lbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuZWxlbWVudC5pZCA9PT0gZnJhZ21lbnQ7XG4gICAgfSk7XG59XG5leHBvcnRzLmdldExpbmVFbGVtZW50Rm9yRnJhZ21lbnQgPSBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxldCBjYWNoZWRTZXR0aW5ncyA9IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGdldERhdGEoa2V5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbmZ1bmN0aW9uIGdldFNldHRpbmdzKCkge1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U2V0dGluZ3MgPSBnZXRTZXR0aW5ncztcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var i=t[o]={i:o,l:!1,exports:{}};return e[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});let o=void 0;function i(e){const t=document.getElementById("vscode-markdown-preview-data");if(t){const n=t.getAttribute(e);if(n)return JSON.parse(n)}throw new Error(`Could not load data for ${e}`)}t.getData=i,t.getSettings=function(){if(o)return o;if(o=i("data-settings"))return o;throw new Error("Could not load settings")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const o=n(0);function i(e){return t=0,n=o.getSettings().lineCount-1,i=e,Math.min(n,Math.max(t,i));var t,n,i}const r=(()=>{let e;return()=>{if(!e){e=[{element:document.body,line:0}];for(const t of document.getElementsByClassName("code-line")){const n=+t.getAttribute("data-line");isNaN(n)||e.push({element:t,line:n})}}return e}})();function s(e){const t=Math.floor(e),n=r();let o=n[0]||null;for(const e of n){if(e.line===t)return{previous:e,next:void 0};if(e.line>t)return{previous:o,next:e};o=e}return{previous:o}}function c(e){const t=r(),n=e-window.scrollY;let o=-1,i=t.length-1;for(;o+1=n?i=e:o=e}const s=t[i],c=s.element.getBoundingClientRect();if(i>=1&&c.top>n){return{previous:t[o],next:s}}return{previous:s}}t.getElementsForSourceLine=s,t.getLineElementsAtPageOffset=c,t.scrollToRevealSourceLine=function(e){if(!o.getSettings().scrollPreviewWithEditor)return;if(e<=0)return void window.scroll(window.scrollX,0);const{previous:t,next:n}=s(e);if(!t)return;let i=0;const r=t.element.getBoundingClientRect(),c=r.top;if(n&&n.line!==t.line)i=c+(e-t.line)/(n.line-t.line)*(n.element.getBoundingClientRect().top-c);else{const t=e-Math.floor(e);i=c+r.height*t}window.scroll(window.scrollX,Math.max(1,window.scrollY+i))},t.getEditorLineNumberForPageOffset=function(e){const{previous:t,next:n}=c(e);if(t){const o=t.element.getBoundingClientRect(),r=e-window.scrollY-o.top;if(n){const e=r/(n.element.getBoundingClientRect().top-o.top);return i(t.line+e*(n.line-t.line))}{const e=r/o.height;return i(t.line+e)}}return null},t.getLineElementForFragment=function(e){return r().find(t=>t.element.id===e)}},,,,,function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){(function(t){var n="Expected a function",o=NaN,i="[object Symbol]",r=/^\s+|\s+$/g,s=/^[-+]0x[0-9a-f]+$/i,c=/^0b[01]+$/i,a=/^0o[0-7]+$/i,u=parseInt,l="object"==typeof t&&t&&t.Object===Object&&t,d="object"==typeof self&&self&&self.Object===Object&&self,f=l||d||Function("return this")(),g=Object.prototype.toString,p=Math.max,m=Math.min,v=function(){return f.Date.now()};function h(e,t,o){var i,r,s,c,a,u,l=0,d=!1,f=!1,g=!0;if("function"!=typeof e)throw new TypeError(n);function h(t){var n=i,o=r;return i=r=void 0,l=t,c=e.apply(o,n)}function y(e){var n=e-u;return void 0===u||n>=t||n<0||f&&e-l>=s}function E(){var e=v();if(y(e))return L(e);a=setTimeout(E,function(e){var n=t-(e-u);return f?m(n,s-(e-l)):n}(e))}function L(e){return a=void 0,g&&i?h(e):(i=r=void 0,c)}function M(){var e=v(),n=y(e);if(i=arguments,r=this,u=e,n){if(void 0===a)return function(e){return l=e,a=setTimeout(E,t),d?h(e):c}(u);if(f)return a=setTimeout(E,t),h(u)}return void 0===a&&(a=setTimeout(E,t)),c}return t=b(t)||0,w(o)&&(d=!!o.leading,s=(f="maxWait"in o)?p(b(o.maxWait)||0,t):s,g="trailing"in o?!!o.trailing:g),M.cancel=function(){void 0!==a&&clearTimeout(a),l=0,i=u=r=a=void 0},M.flush=function(){return void 0===a?c:L(v())},M}function w(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function b(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&g.call(e)==i}(e))return o;if(w(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=w(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(r,"");var n=c.test(e);return n||a.test(e)?u(e.slice(2),n?2:8):s.test(e)?o:+e}e.exports=function(e,t,o){var i=!0,r=!0;if("function"!=typeof e)throw new TypeError(n);return w(o)&&(i="leading"in o?!!o.leading:i,r="trailing"in o?!!o.trailing:r),h(e,t,{leading:i,maxWait:t,trailing:r})}}).call(this,n(6))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const o=n(0);t.createPosterForVsCode=(e=>new class{postMessage(t,n){e.postMessage({type:t,source:o.getSettings().source,body:n})}})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.onceDocumentLoaded=function(e){"loading"===document.readyState||"uninitialized"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const o=n(1);t.ActiveLineMarker=class{onDidChangeTextEditorSelection(e){const{previous:t}=o.getElementsForSourceLine(e);this._update(t&&t.element)}_update(e){this._unmarkActiveElement(this._current),this._markActiveElement(e),this._current=e}_unmarkActiveElement(e){e&&(e.className=e.className.replace(/\bcode-active-line\b/g,""))}_markActiveElement(e){e&&(e.className+=" code-active-line")}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const o=n(10),i=n(9),r=n(8),s=n(1),c=n(0),a=n(7);let u=!0;const l=new o.ActiveLineMarker,d=c.getSettings(),f=acquireVsCodeApi();let g=c.getData("data-state");f.setState(g);const p=r.createPosterForVsCode(f);window.cspAlerter.setPoster(p),window.styleLoadingMonitor.setPoster(p),window.onload=(()=>{v()}),i.onceDocumentLoaded(()=>{d.scrollPreviewWithEditor&&setTimeout(()=>{if(g.fragment){const e=s.getLineElementForFragment(g.fragment);e&&(u=!0,s.scrollToRevealSourceLine(e.line))}else{const e=+d.line;isNaN(e)||(u=!0,s.scrollToRevealSourceLine(e))}},0)});const m=(()=>{const e=a(e=>{u=!0,s.scrollToRevealSourceLine(e)},50);return(t,n)=>{isNaN(t)||(n.line=t,e(t))}})();let v=a(()=>{const e=[];let t=document.getElementsByTagName("img");if(t){let n;for(n=0;n{u=!0,v()},!0),window.addEventListener("message",e=>{if(e.data.source===d.source)switch(e.data.type){case"onDidChangeTextEditorSelection":l.onDidChangeTextEditorSelection(e.data.line);break;case"updateView":m(e.data.line,d)}},!1),document.addEventListener("dblclick",e=>{if(!d.doubleClickToSwitchToEditor)return;for(let t=e.target;t;t=t.parentNode)if("A"===t.tagName)return;const t=e.pageY,n=s.getEditorLineNumberForPageOffset(t);"number"!=typeof n||isNaN(n)||p.postMessage("didClick",{line:Math.floor(n)})});const h=["http:","https:","mailto:","vscode:","vscode-insiders"];document.addEventListener("click",e=>{if(!e)return;let t=e.target;for(;t;){if(t.tagName&&"A"===t.tagName&&t.href){if(t.getAttribute("href").startsWith("#"))return;if(h.some(e=>t.href.startsWith(e)))return;const n=t.getAttribute("data-href")||t.getAttribute("href");return/^[a-z\-]+:/i.test(n)?void 0:(p.postMessage("openLink",{href:n}),e.preventDefault(),void e.stopPropagation())}t=t.parentNode}},!0),window.addEventListener("scroll",a(()=>{if(u)u=!1;else{const e=s.getEditorLineNumberForPageOffset(window.scrollY);"number"!=typeof e||isNaN(e)||(p.postMessage("revealLine",{line:e}),g.line=e,f.setState(g))}},50))}]); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvc2V0dGluZ3MudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvc2Nyb2xsLXN5bmMudHMiLCJ3ZWJwYWNrOi8vLyh3ZWJwYWNrKS9idWlsZGluL2dsb2JhbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbG9kYXNoLnRocm90dGxlL2luZGV4LmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9ldmVudHMudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvYWN0aXZlTGluZU1hcmtlci50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9pbmRleC50cyJdLCJuYW1lcyI6WyJpbnN0YWxsZWRNb2R1bGVzIiwiX193ZWJwYWNrX3JlcXVpcmVfXyIsIm1vZHVsZUlkIiwiZXhwb3J0cyIsIm1vZHVsZSIsImkiLCJsIiwibW9kdWxlcyIsImNhbGwiLCJtIiwiYyIsImQiLCJuYW1lIiwiZ2V0dGVyIiwibyIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiY29uZmlndXJhYmxlIiwiZW51bWVyYWJsZSIsImdldCIsInIiLCJ2YWx1ZSIsIm4iLCJfX2VzTW9kdWxlIiwib2JqZWN0IiwicHJvcGVydHkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsInAiLCJzIiwiY2FjaGVkU2V0dGluZ3MiLCJ1bmRlZmluZWQiLCJnZXREYXRhIiwia2V5IiwiZWxlbWVudCIsImRvY3VtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJkYXRhIiwiZ2V0QXR0cmlidXRlIiwiSlNPTiIsInBhcnNlIiwiRXJyb3IiLCJnZXRTZXR0aW5ncyIsInNldHRpbmdzXzEiLCJjbGFtcExpbmUiLCJsaW5lIiwibWluIiwibWF4IiwibGluZUNvdW50IiwiTWF0aCIsImdldENvZGVMaW5lRWxlbWVudHMiLCJlbGVtZW50cyIsImJvZHkiLCJnZXRFbGVtZW50c0J5Q2xhc3NOYW1lIiwiaXNOYU4iLCJwdXNoIiwiZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lIiwidGFyZ2V0TGluZSIsImxpbmVOdW1iZXIiLCJmbG9vciIsImxpbmVzIiwicHJldmlvdXMiLCJlbnRyeSIsIm5leHQiLCJnZXRMaW5lRWxlbWVudHNBdFBhZ2VPZmZzZXQiLCJvZmZzZXQiLCJwb3NpdGlvbiIsIndpbmRvdyIsInNjcm9sbFkiLCJsbyIsImhpIiwibGVuZ3RoIiwibWlkIiwiYm91bmRzIiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwidG9wIiwiaGVpZ2h0IiwiaGlFbGVtZW50IiwiaGlCb3VuZHMiLCJzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUiLCJzY3JvbGxQcmV2aWV3V2l0aEVkaXRvciIsInNjcm9sbCIsInNjcm9sbFgiLCJzY3JvbGxUbyIsInJlY3QiLCJwcmV2aW91c1RvcCIsInByb2dyZXNzSW5FbGVtZW50IiwiZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQiLCJwcmV2aW91c0JvdW5kcyIsIm9mZnNldEZyb21QcmV2aW91cyIsInByb2dyZXNzQmV0d2VlbkVsZW1lbnRzIiwicHJvZ3Jlc3NXaXRoaW5FbGVtZW50IiwiZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudCIsImZyYWdtZW50IiwiZmluZCIsImlkIiwiZyIsInRoaXMiLCJGdW5jdGlvbiIsImV2YWwiLCJlIiwiZ2xvYmFsIiwiRlVOQ19FUlJPUl9URVhUIiwiTkFOIiwic3ltYm9sVGFnIiwicmVUcmltIiwicmVJc0JhZEhleCIsInJlSXNCaW5hcnkiLCJyZUlzT2N0YWwiLCJmcmVlUGFyc2VJbnQiLCJwYXJzZUludCIsImZyZWVHbG9iYWwiLCJmcmVlU2VsZiIsInNlbGYiLCJyb290Iiwib2JqZWN0VG9TdHJpbmciLCJ0b1N0cmluZyIsIm5hdGl2ZU1heCIsIm5hdGl2ZU1pbiIsIm5vdyIsIkRhdGUiLCJkZWJvdW5jZSIsImZ1bmMiLCJ3YWl0Iiwib3B0aW9ucyIsImxhc3RBcmdzIiwibGFzdFRoaXMiLCJtYXhXYWl0IiwicmVzdWx0IiwidGltZXJJZCIsImxhc3RDYWxsVGltZSIsImxhc3RJbnZva2VUaW1lIiwibGVhZGluZyIsIm1heGluZyIsInRyYWlsaW5nIiwiVHlwZUVycm9yIiwiaW52b2tlRnVuYyIsInRpbWUiLCJhcmdzIiwidGhpc0FyZyIsImFwcGx5Iiwic2hvdWxkSW52b2tlIiwidGltZVNpbmNlTGFzdENhbGwiLCJ0aW1lckV4cGlyZWQiLCJ0cmFpbGluZ0VkZ2UiLCJzZXRUaW1lb3V0IiwicmVtYWluaW5nV2FpdCIsImRlYm91bmNlZCIsImlzSW52b2tpbmciLCJhcmd1bWVudHMiLCJsZWFkaW5nRWRnZSIsInRvTnVtYmVyIiwiaXNPYmplY3QiLCJjYW5jZWwiLCJjbGVhclRpbWVvdXQiLCJmbHVzaCIsInR5cGUiLCJpc09iamVjdExpa2UiLCJpc1N5bWJvbCIsIm90aGVyIiwidmFsdWVPZiIsInJlcGxhY2UiLCJpc0JpbmFyeSIsInRlc3QiLCJzbGljZSIsImNyZWF0ZVBvc3RlckZvclZzQ29kZSIsInZzY29kZSIsIltvYmplY3QgT2JqZWN0XSIsInBvc3RNZXNzYWdlIiwic291cmNlIiwib25jZURvY3VtZW50TG9hZGVkIiwiZiIsInJlYWR5U3RhdGUiLCJhZGRFdmVudExpc3RlbmVyIiwic2Nyb2xsX3N5bmNfMSIsIkFjdGl2ZUxpbmVNYXJrZXIiLCJfdXBkYXRlIiwiYmVmb3JlIiwiX3VubWFya0FjdGl2ZUVsZW1lbnQiLCJfY3VycmVudCIsIl9tYXJrQWN0aXZlRWxlbWVudCIsImNsYXNzTmFtZSIsImFjdGl2ZUxpbmVNYXJrZXJfMSIsImV2ZW50c18xIiwibWVzc2FnaW5nXzEiLCJ0aHJvdHRsZSIsInNjcm9sbERpc2FibGVkIiwibWFya2VyIiwic2V0dGluZ3MiLCJhY3F1aXJlVnNDb2RlQXBpIiwic3RhdGUiLCJzZXRTdGF0ZSIsIm1lc3NhZ2luZyIsImNzcEFsZXJ0ZXIiLCJzZXRQb3N0ZXIiLCJzdHlsZUxvYWRpbmdNb25pdG9yIiwib25sb2FkIiwidXBkYXRlSW1hZ2VTaXplcyIsImluaXRpYWxMaW5lIiwib25VcGRhdGVWaWV3IiwiZG9TY3JvbGwiLCJpbWFnZUluZm8iLCJpbWFnZXMiLCJnZXRFbGVtZW50c0J5VGFnTmFtZSIsImltZyIsImNsYXNzTGlzdCIsImNvbnRhaW5zIiwicmVtb3ZlIiwid2lkdGgiLCJldmVudCIsIm9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbiIsImRvdWJsZUNsaWNrVG9Td2l0Y2hUb0VkaXRvciIsIm5vZGUiLCJ0YXJnZXQiLCJwYXJlbnROb2RlIiwidGFnTmFtZSIsInBhZ2VZIiwicGFzc1Rocm91Z2hMaW5rU2NoZW1lcyIsImhyZWYiLCJzdGFydHNXaXRoIiwic29tZSIsInNjaGVtZSIsImhyZWZUZXh0IiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iXSwibWFwcGluZ3MiOiJhQUNBLElBQUFBLEtBR0EsU0FBQUMsRUFBQUMsR0FHQSxHQUFBRixFQUFBRSxHQUNBLE9BQUFGLEVBQUFFLEdBQUFDLFFBR0EsSUFBQUMsRUFBQUosRUFBQUUsSUFDQUcsRUFBQUgsRUFDQUksR0FBQSxFQUNBSCxZQVVBLE9BTkFJLEVBQUFMLEdBQUFNLEtBQUFKLEVBQUFELFFBQUFDLElBQUFELFFBQUFGLEdBR0FHLEVBQUFFLEdBQUEsRUFHQUYsRUFBQUQsUUFLQUYsRUFBQVEsRUFBQUYsRUFHQU4sRUFBQVMsRUFBQVYsRUFHQUMsRUFBQVUsRUFBQSxTQUFBUixFQUFBUyxFQUFBQyxHQUNBWixFQUFBYSxFQUFBWCxFQUFBUyxJQUNBRyxPQUFBQyxlQUFBYixFQUFBUyxHQUNBSyxjQUFBLEVBQ0FDLFlBQUEsRUFDQUMsSUFBQU4sS0FNQVosRUFBQW1CLEVBQUEsU0FBQWpCLEdBQ0FZLE9BQUFDLGVBQUFiLEVBQUEsY0FBaURrQixPQUFBLEtBSWpEcEIsRUFBQXFCLEVBQUEsU0FBQWxCLEdBQ0EsSUFBQVMsRUFBQVQsS0FBQW1CLFdBQ0EsV0FBMkIsT0FBQW5CLEVBQUEsU0FDM0IsV0FBaUMsT0FBQUEsR0FFakMsT0FEQUgsRUFBQVUsRUFBQUUsRUFBQSxJQUFBQSxHQUNBQSxHQUlBWixFQUFBYSxFQUFBLFNBQUFVLEVBQUFDLEdBQXNELE9BQUFWLE9BQUFXLFVBQUFDLGVBQUFuQixLQUFBZ0IsRUFBQUMsSUFHdER4QixFQUFBMkIsRUFBQSxHQUlBM0IsSUFBQTRCLEVBQUEsbUNDOURBZCxPQUFBQyxlQUFBYixFQUFBLGNBQThDa0IsT0FBQSxJQUM5QyxJQUFBUyxPQUFBQyxFQUNBLFNBQUFDLEVBQUFDLEdBQ0EsTUFBQUMsRUFBQUMsU0FBQUMsZUFBQSxnQ0FDQSxHQUFBRixFQUFBLENBQ0EsTUFBQUcsRUFBQUgsRUFBQUksYUFBQUwsR0FDQSxHQUFBSSxFQUNBLE9BQUFFLEtBQUFDLE1BQUFILEdBR0EsVUFBQUksaUNBQStDUixLQUUvQzlCLEVBQUE2QixVQVdBN0IsRUFBQXVDLFlBVkEsV0FDQSxHQUFBWixFQUNBLE9BQUFBLEVBR0EsR0FEQUEsRUFBQUUsRUFBQSxpQkFFQSxPQUFBRixFQUVBLFVBQUFXLE1BQUEsMERDckJBMUIsT0FBQUMsZUFBQWIsRUFBQSxjQUE4Q2tCLE9BQUEsSUFDOUMsTUFBQXNCLEVBQUExQyxFQUFBLEdBSUEsU0FBQTJDLEVBQUFDLEdBQ0EsT0FKQUMsRUFJQSxFQUpBQyxFQUlBSixFQUFBRCxjQUFBTSxVQUFBLEVBSkEzQixFQUlBd0IsRUFIQUksS0FBQUgsSUFBQUMsRUFBQUUsS0FBQUYsSUFBQUQsRUFBQXpCLElBREEsSUFBQXlCLEVBQUFDLEVBQUExQixFQU1BLE1BQUE2QixFQUFBLE1BQ0EsSUFBQUMsRUFDQSxXQUNBLElBQUFBLEVBQUEsQ0FDQUEsSUFBeUJqQixRQUFBQyxTQUFBaUIsS0FBQVAsS0FBQSxJQUN6QixVQUFBWCxLQUFBQyxTQUFBa0IsdUJBQUEsY0FDQSxNQUFBUixHQUFBWCxFQUFBSSxhQUFBLGFBQ0FnQixNQUFBVCxJQUNBTSxFQUFBSSxNQUFtQ3JCLFVBQUFXLFVBSW5DLE9BQUFNLElBWkEsR0FxQkEsU0FBQUssRUFBQUMsR0FDQSxNQUFBQyxFQUFBVCxLQUFBVSxNQUFBRixHQUNBRyxFQUFBVixJQUNBLElBQUFXLEVBQUFELEVBQUEsU0FDQSxVQUFBRSxLQUFBRixFQUFBLENBQ0EsR0FBQUUsRUFBQWpCLE9BQUFhLEVBQ0EsT0FBb0JHLFNBQUFDLEVBQUFDLFVBQUFoQyxHQUVwQixHQUFBK0IsRUFBQWpCLEtBQUFhLEVBQ0EsT0FBb0JHLFdBQUFFLEtBQUFELEdBRXBCRCxFQUFBQyxFQUVBLE9BQVlELFlBTVosU0FBQUcsRUFBQUMsR0FDQSxNQUFBTCxFQUFBVixJQUNBZ0IsRUFBQUQsRUFBQUUsT0FBQUMsUUFDQSxJQUFBQyxHQUFBLEVBQ0FDLEVBQUFWLEVBQUFXLE9BQUEsRUFDQSxLQUFBRixFQUFBLEVBQUFDLEdBQUEsQ0FDQSxNQUFBRSxFQUFBdkIsS0FBQVUsT0FBQVUsRUFBQUMsR0FBQSxHQUNBRyxFQUFBYixFQUFBWSxHQUFBdEMsUUFBQXdDLHdCQUNBRCxFQUFBRSxJQUFBRixFQUFBRyxRQUFBVixFQUNBSSxFQUFBRSxFQUdBSCxFQUFBRyxFQUdBLE1BQUFLLEVBQUFqQixFQUFBVSxHQUNBUSxFQUFBRCxFQUFBM0MsUUFBQXdDLHdCQUNBLEdBQUFKLEdBQUEsR0FBQVEsRUFBQUgsSUFBQVQsRUFBQSxDQUVBLE9BQWdCTCxTQURoQkQsRUFBQVMsR0FDZ0JOLEtBQUFjLEdBRWhCLE9BQVloQixTQUFBZ0IsR0F6QloxRSxFQUFBcUQsMkJBMkJBckQsRUFBQTZELDhCQStCQTdELEVBQUE0RSx5QkEzQkEsU0FBQWxDLEdBQ0EsSUFBQUYsRUFBQUQsY0FBQXNDLHdCQUNBLE9BRUEsR0FBQW5DLEdBQUEsRUFFQSxZQURBc0IsT0FBQWMsT0FBQWQsT0FBQWUsUUFBQSxHQUdBLE1BQUFyQixTQUFXQSxFQUFBRSxRQUFpQlAsRUFBQVgsR0FDNUIsSUFBQWdCLEVBQ0EsT0FFQSxJQUFBc0IsRUFBQSxFQUNBLE1BQUFDLEVBQUF2QixFQUFBM0IsUUFBQXdDLHdCQUNBVyxFQUFBRCxFQUFBVCxJQUNBLEdBQUFaLEtBQUFsQixPQUFBZ0IsRUFBQWhCLEtBSUFzQyxFQUFBRSxHQUZBeEMsRUFBQWdCLEVBQUFoQixPQUFBa0IsRUFBQWxCLEtBQUFnQixFQUFBaEIsT0FDQWtCLEVBQUE3QixRQUFBd0Msd0JBQUFDLElBQUFVLE9BR0EsQ0FDQSxNQUFBQyxFQUFBekMsRUFBQUksS0FBQVUsTUFBQWQsR0FDQXNDLEVBQUFFLEVBQUFELEVBQUFSLE9BQUFVLEVBRUFuQixPQUFBYyxPQUFBZCxPQUFBZSxRQUFBakMsS0FBQUYsSUFBQSxFQUFBb0IsT0FBQUMsUUFBQWUsS0FxQkFoRixFQUFBb0YsaUNBbEJBLFNBQUF0QixHQUNBLE1BQUFKLFNBQVdBLEVBQUFFLFFBQWlCQyxFQUFBQyxHQUM1QixHQUFBSixFQUFBLENBQ0EsTUFBQTJCLEVBQUEzQixFQUFBM0IsUUFBQXdDLHdCQUNBZSxFQUFBeEIsRUFBQUUsT0FBQUMsUUFBQW9CLEVBQUFiLElBQ0EsR0FBQVosRUFBQSxDQUNBLE1BQUEyQixFQUFBRCxHQUFBMUIsRUFBQTdCLFFBQUF3Qyx3QkFBQUMsSUFBQWEsRUFBQWIsS0FFQSxPQUFBL0IsRUFEQWlCLEVBQUFoQixLQUFBNkMsR0FBQTNCLEVBQUFsQixLQUFBZ0IsRUFBQWhCLE9BR0EsQ0FDQSxNQUFBOEMsRUFBQUYsRUFBQUQsRUFBQSxPQUVBLE9BQUE1QyxFQURBaUIsRUFBQWhCLEtBQUE4QyxJQUlBLGFBV0F4RixFQUFBeUYsMEJBTEEsU0FBQUMsR0FDQSxPQUFBM0MsSUFBQTRDLEtBQUE1RCxHQUNBQSxVQUFBNkQsS0FBQUYsdUJDcElBLElBQUFHLEVBR0FBLEVBQUEsV0FDQSxPQUFBQyxLQURBLEdBSUEsSUFFQUQsS0FBQUUsU0FBQSxjQUFBQSxLQUFBLEVBQUFDLE1BQUEsUUFDQyxNQUFBQyxHQUVELGlCQUFBakMsU0FBQTZCLEVBQUE3QixRQU9BL0QsRUFBQUQsUUFBQTZGLG9CQ25CQSxTQUFBSyxHQVVBLElBQUFDLEVBQUEsc0JBR0FDLEVBQUEsSUFHQUMsRUFBQSxrQkFHQUMsRUFBQSxhQUdBQyxFQUFBLHFCQUdBQyxFQUFBLGFBR0FDLEVBQUEsY0FHQUMsRUFBQUMsU0FHQUMsRUFBQSxpQkFBQVYsUUFBQXRGLGlCQUFBc0YsRUFHQVcsRUFBQSxpQkFBQUMsaUJBQUFsRyxpQkFBQWtHLEtBR0FDLEVBQUFILEdBQUFDLEdBQUFkLFNBQUEsY0FBQUEsR0FVQWlCLEVBUEFwRyxPQUFBVyxVQU9BMEYsU0FHQUMsRUFBQXBFLEtBQUFGLElBQ0F1RSxFQUFBckUsS0FBQUgsSUFrQkF5RSxFQUFBLFdBQ0EsT0FBQUwsRUFBQU0sS0FBQUQsT0F5REEsU0FBQUUsRUFBQUMsRUFBQUMsRUFBQUMsR0FDQSxJQUFBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUFBLEVBQ0FDLEdBQUEsRUFDQUMsR0FBQSxFQUNBQyxHQUFBLEVBRUEsc0JBQUFaLEVBQ0EsVUFBQWEsVUFBQWpDLEdBVUEsU0FBQWtDLEVBQUFDLEdBQ0EsSUFBQUMsRUFBQWIsRUFDQWMsRUFBQWIsRUFLQSxPQUhBRCxFQUFBQyxPQUFBL0YsRUFDQW9HLEVBQUFNLEVBQ0FULEVBQUFOLEVBQUFrQixNQUFBRCxFQUFBRCxHQXFCQSxTQUFBRyxFQUFBSixHQUNBLElBQUFLLEVBQUFMLEVBQUFQLEVBTUEsWUFBQW5HLElBQUFtRyxHQUFBWSxHQUFBbkIsR0FDQW1CLEVBQUEsR0FBQVQsR0FOQUksRUFBQU4sR0FNQUosRUFHQSxTQUFBZ0IsSUFDQSxJQUFBTixFQUFBbEIsSUFDQSxHQUFBc0IsRUFBQUosR0FDQSxPQUFBTyxFQUFBUCxHQUdBUixFQUFBZ0IsV0FBQUYsRUF6QkEsU0FBQU4sR0FDQSxJQUVBVCxFQUFBTCxHQUZBYyxFQUFBUCxHQUlBLE9BQUFHLEVBQUFmLEVBQUFVLEVBQUFELEdBSEFVLEVBQUFOLElBR0FILEVBb0JBa0IsQ0FBQVQsSUFHQSxTQUFBTyxFQUFBUCxHQUtBLE9BSkFSLE9BQUFsRyxFQUlBdUcsR0FBQVQsRUFDQVcsRUFBQUMsSUFFQVosRUFBQUMsT0FBQS9GLEVBQ0FpRyxHQWVBLFNBQUFtQixJQUNBLElBQUFWLEVBQUFsQixJQUNBNkIsRUFBQVAsRUFBQUosR0FNQSxHQUpBWixFQUFBd0IsVUFDQXZCLEVBQUE3QixLQUNBaUMsRUFBQU8sRUFFQVcsRUFBQSxDQUNBLFFBQUFySCxJQUFBa0csRUFDQSxPQXZFQSxTQUFBUSxHQU1BLE9BSkFOLEVBQUFNLEVBRUFSLEVBQUFnQixXQUFBRixFQUFBcEIsR0FFQVMsRUFBQUksRUFBQUMsR0FBQVQsRUFpRUFzQixDQUFBcEIsR0FFQSxHQUFBRyxFQUdBLE9BREFKLEVBQUFnQixXQUFBRixFQUFBcEIsR0FDQWEsRUFBQU4sR0FNQSxZQUhBbkcsSUFBQWtHLElBQ0FBLEVBQUFnQixXQUFBRixFQUFBcEIsSUFFQUssRUFJQSxPQXhHQUwsRUFBQTRCLEVBQUE1QixJQUFBLEVBQ0E2QixFQUFBNUIsS0FDQVEsSUFBQVIsRUFBQVEsUUFFQUwsR0FEQU0sRUFBQSxZQUFBVCxHQUNBUCxFQUFBa0MsRUFBQTNCLEVBQUFHLFVBQUEsRUFBQUosR0FBQUksRUFDQU8sRUFBQSxhQUFBVixNQUFBVSxZQWlHQWEsRUFBQU0sT0FuQ0EsZ0JBQ0ExSCxJQUFBa0csR0FDQXlCLGFBQUF6QixHQUVBRSxFQUFBLEVBQ0FOLEVBQUFLLEVBQUFKLEVBQUFHLE9BQUFsRyxHQStCQW9ILEVBQUFRLE1BNUJBLFdBQ0EsWUFBQTVILElBQUFrRyxFQUFBRCxFQUFBZ0IsRUFBQXpCLE1BNEJBNEIsRUEwRkEsU0FBQUssRUFBQW5JLEdBQ0EsSUFBQXVJLFNBQUF2SSxFQUNBLFFBQUFBLElBQUEsVUFBQXVJLEdBQUEsWUFBQUEsR0E0RUEsU0FBQUwsRUFBQWxJLEdBQ0Esb0JBQUFBLEVBQ0EsT0FBQUEsRUFFQSxHQWhDQSxTQUFBQSxHQUNBLHVCQUFBQSxHQXRCQSxTQUFBQSxHQUNBLFFBQUFBLEdBQUEsaUJBQUFBLEVBc0JBd0ksQ0FBQXhJLElBQUE4RixFQUFBM0csS0FBQWEsSUFBQW1GLEVBOEJBc0QsQ0FBQXpJLEdBQ0EsT0FBQWtGLEVBRUEsR0FBQWlELEVBQUFuSSxHQUFBLENBQ0EsSUFBQTBJLEVBQUEsbUJBQUExSSxFQUFBMkksUUFBQTNJLEVBQUEySSxVQUFBM0ksRUFDQUEsRUFBQW1JLEVBQUFPLEtBQUEsR0FBQUEsRUFFQSxvQkFBQTFJLEVBQ0EsV0FBQUEsT0FFQUEsSUFBQTRJLFFBQUF4RCxFQUFBLElBQ0EsSUFBQXlELEVBQUF2RCxFQUFBd0QsS0FBQTlJLEdBQ0EsT0FBQTZJLEdBQUF0RCxFQUFBdUQsS0FBQTlJLEdBQ0F3RixFQUFBeEYsRUFBQStJLE1BQUEsR0FBQUYsRUFBQSxLQUNBeEQsRUFBQXlELEtBQUE5SSxHQUFBa0YsR0FBQWxGLEVBR0FqQixFQUFBRCxRQTlJQSxTQUFBdUgsRUFBQUMsRUFBQUMsR0FDQSxJQUFBUSxHQUFBLEVBQ0FFLEdBQUEsRUFFQSxzQkFBQVosRUFDQSxVQUFBYSxVQUFBakMsR0FNQSxPQUpBa0QsRUFBQTVCLEtBQ0FRLEVBQUEsWUFBQVIsTUFBQVEsVUFDQUUsRUFBQSxhQUFBVixNQUFBVSxZQUVBYixFQUFBQyxFQUFBQyxHQUNBUyxVQUNBTCxRQUFBSixFQUNBVyw4RENqVEF2SCxPQUFBQyxlQUFBYixFQUFBLGNBQThDa0IsT0FBQSxJQUM5QyxNQUFBc0IsRUFBQTFDLEVBQUEsR0FDQUUsRUFBQWtLLHNCQUFBLENBQUFDLEdBQ0EsVUFDQUMsWUFBQVgsRUFBQXhHLEdBQ0FrSCxFQUFBRSxhQUNBWixPQUNBYSxPQUFBOUgsRUFBQUQsY0FBQStILE9BQ0FySCwwQ0NSQXJDLE9BQUFDLGVBQUFiLEVBQUEsY0FBOENrQixPQUFBLElBUzlDbEIsRUFBQXVLLG1CQVJBLFNBQUFDLEdBQ0EsWUFBQXhJLFNBQUF5SSxZQUFBLGtCQUFBekksU0FBQXlJLFdBQ0F6SSxTQUFBMEksaUJBQUEsbUJBQUFGLEdBR0FBLG1DQ1ZBNUosT0FBQUMsZUFBQWIsRUFBQSxjQUE4Q2tCLE9BQUEsSUFLOUMsTUFBQXlKLEVBQUE3SyxFQUFBLEdBd0JBRSxFQUFBNEssdUJBdEJBUiwrQkFBQTFILEdBQ0EsTUFBQWdCLFNBQWVBLEdBQVdpSCxFQUFBdEgseUJBQUFYLEdBQzFCb0QsS0FBQStFLFFBQUFuSCxLQUFBM0IsU0FFQXFJLFFBQUFVLEdBQ0FoRixLQUFBaUYscUJBQUFqRixLQUFBa0YsVUFDQWxGLEtBQUFtRixtQkFBQUgsR0FDQWhGLEtBQUFrRixTQUFBRixFQUVBVixxQkFBQXJJLEdBQ0FBLElBR0FBLEVBQUFtSixVQUFBbkosRUFBQW1KLFVBQUFwQixRQUFBLDZCQUVBTSxtQkFBQXJJLEdBQ0FBLElBR0FBLEVBQUFtSixXQUFBLHFEQ3RCQXRLLE9BQUFDLGVBQUFiLEVBQUEsY0FBOENrQixPQUFBLElBQzlDLE1BQUFpSyxFQUFBckwsRUFBQSxJQUNBc0wsRUFBQXRMLEVBQUEsR0FDQXVMLEVBQUF2TCxFQUFBLEdBQ0E2SyxFQUFBN0ssRUFBQSxHQUNBMEMsRUFBQTFDLEVBQUEsR0FDQXdMLEVBQUF4TCxFQUFBLEdBQ0EsSUFBQXlMLEdBQUEsRUFDQSxNQUFBQyxFQUFBLElBQUFMLEVBQUFQLGlCQUNBYSxFQUFBakosRUFBQUQsY0FDQTRILEVBQUF1QixtQkFFQSxJQUFBQyxFQUFBbkosRUFBQVgsUUFBQSxjQUNBc0ksRUFBQXlCLFNBQUFELEdBQ0EsTUFBQUUsRUFBQVIsRUFBQW5CLHNCQUFBQyxHQUNBbkcsT0FBQThILFdBQUFDLFVBQUFGLEdBQ0E3SCxPQUFBZ0ksb0JBQUFELFVBQUFGLEdBQ0E3SCxPQUFBaUksT0FBQSxNQUNBQyxNQUVBZCxFQUFBYixtQkFBQSxLQUNBa0IsRUFBQTVHLHlCQUNBaUUsV0FBQSxLQUVBLEdBQUE2QyxFQUFBakcsU0FBQSxDQUNBLE1BQUEzRCxFQUFBNEksRUFBQWxGLDBCQUFBa0csRUFBQWpHLFVBQ0EzRCxJQUNBd0osR0FBQSxFQUNBWixFQUFBL0YseUJBQUE3QyxFQUFBVyxXQUdBLENBQ0EsTUFBQXlKLEdBQUFWLEVBQUEvSSxLQUNBUyxNQUFBZ0osS0FDQVosR0FBQSxFQUNBWixFQUFBL0YseUJBQUF1SCxNQUdTLEtBR1QsTUFBQUMsRUFBQSxNQUNBLE1BQUFDLEVBQUFmLEVBQUE1SSxJQUNBNkksR0FBQSxFQUNBWixFQUFBL0YseUJBQUFsQyxJQUNLLElBQ0wsT0FBQUEsRUFBQStJLEtBQ0F0SSxNQUFBVCxLQUNBK0ksRUFBQS9JLE9BQ0EySixFQUFBM0osTUFSQSxHQVlBLElBQUF3SixFQUFBWixFQUFBLEtBQ0EsTUFBQWdCLEtBQ0EsSUFBQUMsRUFBQXZLLFNBQUF3SyxxQkFBQSxPQUNBLEdBQUFELEVBQUEsQ0FDQSxJQUFBck0sRUFDQSxJQUFBQSxFQUFBLEVBQW1CQSxFQUFBcU0sRUFBQW5JLE9BQW1CbEUsSUFBQSxDQUN0QyxNQUFBdU0sRUFBQUYsRUFBQXJNLEdBQ0F1TSxFQUFBQyxVQUFBQyxTQUFBLFlBQ0FGLEVBQUFDLFVBQUFFLE9BQUEsV0FFQU4sRUFBQWxKLE1BQ0F3QyxHQUFBNkcsRUFBQTdHLEdBQ0FuQixPQUFBZ0ksRUFBQWhJLE9BQ0FvSSxNQUFBSixFQUFBSSxRQUdBaEIsRUFBQXhCLFlBQUEsa0JBQUFpQyxLQUVDLElBQ0R0SSxPQUFBMEcsaUJBQUEsY0FDQWEsR0FBQSxFQUNBVyxNQUNDLEdBQ0RsSSxPQUFBMEcsaUJBQUEsVUFBQW9DLElBQ0EsR0FBQUEsRUFBQTVLLEtBQUFvSSxTQUFBbUIsRUFBQW5CLE9BR0EsT0FBQXdDLEVBQUE1SyxLQUFBdUgsTUFDQSxxQ0FDQStCLEVBQUF1QiwrQkFBQUQsRUFBQTVLLEtBQUFRLE1BQ0EsTUFDQSxpQkFDQTBKLEVBQUFVLEVBQUE1SyxLQUFBUSxLQUFBK0ksTUFHQyxHQUNEekosU0FBQTBJLGlCQUFBLFdBQUFvQyxJQUNBLElBQUFyQixFQUFBdUIsNEJBQ0EsT0FHQSxRQUFBQyxFQUFBSCxFQUFBSSxPQUFpQ0QsRUFBTUEsSUFBQUUsV0FDdkMsU0FBQUYsRUFBQUcsUUFDQSxPQUdBLE1BQUF0SixFQUFBZ0osRUFBQU8sTUFDQTNLLEVBQUFpSSxFQUFBdkYsaUNBQUF0QixHQUNBLGlCQUFBcEIsR0FBQVMsTUFBQVQsSUFDQW1KLEVBQUF4QixZQUFBLFlBQTJDM0gsS0FBQUksS0FBQVUsTUFBQWQsT0FHM0MsTUFBQTRLLEdBQUEsd0RBQ0F0TCxTQUFBMEksaUJBQUEsUUFBQW9DLElBQ0EsSUFBQUEsRUFDQSxPQUVBLElBQUFHLEVBQUFILEVBQUFJLE9BQ0EsS0FBQUQsR0FBQSxDQUNBLEdBQUFBLEVBQUFHLFNBQUEsTUFBQUgsRUFBQUcsU0FBQUgsRUFBQU0sS0FBQSxDQUNBLEdBQUFOLEVBQUE5SyxhQUFBLFFBQUFxTCxXQUFBLEtBQ0EsT0FHQSxHQUFBRixFQUFBRyxLQUFBQyxHQUFBVCxFQUFBTSxLQUFBQyxXQUFBRSxJQUNBLE9BRUEsTUFBQUMsRUFBQVYsRUFBQTlLLGFBQUEsY0FBQThLLEVBQUE5SyxhQUFBLFFBRUEsb0JBQUE2SCxLQUFBMkQsUUFNQSxHQUxBOUIsRUFBQXhCLFlBQUEsWUFBbURrRCxLQUFBSSxJQUNuRGIsRUFBQWMsc0JBQ0FkLEVBQUFlLG1CQUtBWixJQUFBRSxjQUVDLEdBQ0RuSixPQUFBMEcsaUJBQUEsU0FBQVksRUFBQSxLQUNBLEdBQUFDLEVBQ0FBLEdBQUEsTUFFQSxDQUNBLE1BQUE3SSxFQUFBaUksRUFBQXZGLGlDQUFBcEIsT0FBQUMsU0FDQSxpQkFBQXZCLEdBQUFTLE1BQUFULEtBQ0FtSixFQUFBeEIsWUFBQSxjQUFpRDNILFNBQ2pEaUosRUFBQWpKLE9BQ0F5SCxFQUFBeUIsU0FBQUQsTUFHQyIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbiBcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG4gXHRcdFx0XHRnZXQ6IGdldHRlclxuIFx0XHRcdH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSBmdW5jdGlvbihleHBvcnRzKSB7XG4gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMTEpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxldCBjYWNoZWRTZXR0aW5ncyA9IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGdldERhdGEoa2V5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbmZ1bmN0aW9uIGdldFNldHRpbmdzKCkge1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U2V0dGluZ3MgPSBnZXRTZXR0aW5ncztcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5mdW5jdGlvbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpIHtcbiAgICByZXR1cm4gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIHZhbHVlKSk7XG59XG5mdW5jdGlvbiBjbGFtcExpbmUobGluZSkge1xuICAgIHJldHVybiBjbGFtcCgwLCBzZXR0aW5nc18xLmdldFNldHRpbmdzKCkubGluZUNvdW50IC0gMSwgbGluZSk7XG59XG5jb25zdCBnZXRDb2RlTGluZUVsZW1lbnRzID0gKCgpID0+IHtcbiAgICBsZXQgZWxlbWVudHM7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgaWYgKCFlbGVtZW50cykge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBbeyBlbGVtZW50OiBkb2N1bWVudC5ib2R5LCBsaW5lOiAwIH1dO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2NvZGUtbGluZScpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGluZSA9ICtlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1saW5lJyk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50cy5wdXNoKHsgZWxlbWVudDogZWxlbWVudCwgbGluZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsZW1lbnRzO1xuICAgIH07XG59KSgpO1xuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgbWFwIHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxpbmUgaW4gdGhlIGVkaXRvci5cbiAqXG4gKiBJZiBhbiBleGFjdCBtYXRjaCwgcmV0dXJucyBhIHNpbmdsZSBlbGVtZW50LiBJZiB0aGUgbGluZSBpcyBiZXR3ZWVuIGVsZW1lbnRzLFxuICogcmV0dXJucyB0aGUgZWxlbWVudCBwcmlvciB0byBhbmQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGdpdmVuIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGdldEVsZW1lbnRzRm9yU291cmNlTGluZSh0YXJnZXRMaW5lKSB7XG4gICAgY29uc3QgbGluZU51bWJlciA9IE1hdGguZmxvb3IodGFyZ2V0TGluZSk7XG4gICAgY29uc3QgbGluZXMgPSBnZXRDb2RlTGluZUVsZW1lbnRzKCk7XG4gICAgbGV0IHByZXZpb3VzID0gbGluZXNbMF0gfHwgbnVsbDtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGxpbmVzKSB7XG4gICAgICAgIGlmIChlbnRyeS5saW5lID09PSBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91czogZW50cnksIG5leHQ6IHVuZGVmaW5lZCB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGVudHJ5LmxpbmUgPiBsaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBwcmV2aW91cywgbmV4dDogZW50cnkgfTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2aW91cyA9IGVudHJ5O1xuICAgIH1cbiAgICByZXR1cm4geyBwcmV2aW91cyB9O1xufVxuZXhwb3J0cy5nZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUgPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmU7XG4vKipcbiAqIEZpbmQgdGhlIGh0bWwgZWxlbWVudHMgdGhhdCBhcmUgYXQgYSBzcGVjaWZpYyBwaXhlbCBvZmZzZXQgb24gdGhlIHBhZ2UuXG4gKi9cbmZ1bmN0aW9uIGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpIHtcbiAgICBjb25zdCBsaW5lcyA9IGdldENvZGVMaW5lRWxlbWVudHMoKTtcbiAgICBjb25zdCBwb3NpdGlvbiA9IG9mZnNldCAtIHdpbmRvdy5zY3JvbGxZO1xuICAgIGxldCBsbyA9IC0xO1xuICAgIGxldCBoaSA9IGxpbmVzLmxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKGxvICsgMSA8IGhpKSB7XG4gICAgICAgIGNvbnN0IG1pZCA9IE1hdGguZmxvb3IoKGxvICsgaGkpIC8gMik7XG4gICAgICAgIGNvbnN0IGJvdW5kcyA9IGxpbmVzW21pZF0uZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaWYgKGJvdW5kcy50b3AgKyBib3VuZHMuaGVpZ2h0ID49IHBvc2l0aW9uKSB7XG4gICAgICAgICAgICBoaSA9IG1pZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxvID0gbWlkO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGhpRWxlbWVudCA9IGxpbmVzW2hpXTtcbiAgICBjb25zdCBoaUJvdW5kcyA9IGhpRWxlbWVudC5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChoaSA+PSAxICYmIGhpQm91bmRzLnRvcCA+IHBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IGxvRWxlbWVudCA9IGxpbmVzW2xvXTtcbiAgICAgICAgcmV0dXJuIHsgcHJldmlvdXM6IGxvRWxlbWVudCwgbmV4dDogaGlFbGVtZW50IH07XG4gICAgfVxuICAgIHJldHVybiB7IHByZXZpb3VzOiBoaUVsZW1lbnQgfTtcbn1cbmV4cG9ydHMuZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0O1xuLyoqXG4gKiBBdHRlbXB0IHRvIHJldmVhbCB0aGUgZWxlbWVudCBmb3IgYSBzb3VyY2UgbGluZSBpbiB0aGUgZWRpdG9yLlxuICovXG5mdW5jdGlvbiBzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSkge1xuICAgIGlmICghc2V0dGluZ3NfMS5nZXRTZXR0aW5ncygpLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGxpbmUgPD0gMCkge1xuICAgICAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB7IHByZXZpb3VzLCBuZXh0IH0gPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG4gICAgaWYgKCFwcmV2aW91cykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBzY3JvbGxUbyA9IDA7XG4gICAgY29uc3QgcmVjdCA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgcHJldmlvdXNUb3AgPSByZWN0LnRvcDtcbiAgICBpZiAobmV4dCAmJiBuZXh0LmxpbmUgIT09IHByZXZpb3VzLmxpbmUpIHtcbiAgICAgICAgLy8gQmV0d2VlbiB0d28gZWxlbWVudHMuIEdvIHRvIHBlcmNlbnRhZ2Ugb2Zmc2V0IGJldHdlZW4gdGhlbS5cbiAgICAgICAgY29uc3QgYmV0d2VlblByb2dyZXNzID0gKGxpbmUgLSBwcmV2aW91cy5saW5lKSAvIChuZXh0LmxpbmUgLSBwcmV2aW91cy5saW5lKTtcbiAgICAgICAgY29uc3QgZWxlbWVudE9mZnNldCA9IG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c1RvcDtcbiAgICAgICAgc2Nyb2xsVG8gPSBwcmV2aW91c1RvcCArIGJldHdlZW5Qcm9ncmVzcyAqIGVsZW1lbnRPZmZzZXQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBwcm9ncmVzc0luRWxlbWVudCA9IGxpbmUgLSBNYXRoLmZsb29yKGxpbmUpO1xuICAgICAgICBzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgKHJlY3QuaGVpZ2h0ICogcHJvZ3Jlc3NJbkVsZW1lbnQpO1xuICAgIH1cbiAgICB3aW5kb3cuc2Nyb2xsKHdpbmRvdy5zY3JvbGxYLCBNYXRoLm1heCgxLCB3aW5kb3cuc2Nyb2xsWSArIHNjcm9sbFRvKSk7XG59XG5leHBvcnRzLnNjcm9sbFRvUmV2ZWFsU291cmNlTGluZSA9IHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZTtcbmZ1bmN0aW9uIGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCkge1xuICAgIGNvbnN0IHsgcHJldmlvdXMsIG5leHQgfSA9IGdldExpbmVFbGVtZW50c0F0UGFnZU9mZnNldChvZmZzZXQpO1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICBjb25zdCBwcmV2aW91c0JvdW5kcyA9IHByZXZpb3VzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IG9mZnNldEZyb21QcmV2aW91cyA9IChvZmZzZXQgLSB3aW5kb3cuc2Nyb2xsWSAtIHByZXZpb3VzQm91bmRzLnRvcCk7XG4gICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICBjb25zdCBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyA9IG9mZnNldEZyb21QcmV2aW91cyAvIChuZXh0LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NCZXR3ZWVuRWxlbWVudHMgKiAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG4gICAgICAgICAgICByZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3NXaXRoaW5FbGVtZW50ID0gb2Zmc2V0RnJvbVByZXZpb3VzIC8gKHByZXZpb3VzQm91bmRzLmhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gcHJldmlvdXMubGluZSArIHByb2dyZXNzV2l0aGluRWxlbWVudDtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcExpbmUobGluZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5leHBvcnRzLmdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0ID0gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQ7XG4vKipcbiAqIFRyeSB0byBmaW5kIHRoZSBodG1sIGVsZW1lbnQgYnkgdXNpbmcgYSBmcmFnbWVudCBpZFxuICovXG5mdW5jdGlvbiBnZXRMaW5lRWxlbWVudEZvckZyYWdtZW50KGZyYWdtZW50KSB7XG4gICAgcmV0dXJuIGdldENvZGVMaW5lRWxlbWVudHMoKS5maW5kKChlbGVtZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBlbGVtZW50LmVsZW1lbnQuaWQgPT09IGZyYWdtZW50O1xuICAgIH0pO1xufVxuZXhwb3J0cy5nZXRMaW5lRWxlbWVudEZvckZyYWdtZW50ID0gZ2V0TGluZUVsZW1lbnRGb3JGcmFnbWVudDtcbiIsInZhciBnO1xyXG5cclxuLy8gVGhpcyB3b3JrcyBpbiBub24tc3RyaWN0IG1vZGVcclxuZyA9IChmdW5jdGlvbigpIHtcclxuXHRyZXR1cm4gdGhpcztcclxufSkoKTtcclxuXHJcbnRyeSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiBldmFsIGlzIGFsbG93ZWQgKHNlZSBDU1ApXHJcblx0ZyA9IGcgfHwgRnVuY3Rpb24oXCJyZXR1cm4gdGhpc1wiKSgpIHx8ICgxLCBldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2ggKGUpIHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIHRoZSB3aW5kb3cgcmVmZXJlbmNlIGlzIGF2YWlsYWJsZVxyXG5cdGlmICh0eXBlb2Ygd2luZG93ID09PSBcIm9iamVjdFwiKSBnID0gd2luZG93O1xyXG59XHJcblxyXG4vLyBnIGNhbiBzdGlsbCBiZSB1bmRlZmluZWQsIGJ1dCBub3RoaW5nIHRvIGRvIGFib3V0IGl0Li4uXHJcbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXHJcbi8vIGVhc2llciB0byBoYW5kbGUgdGhpcyBjYXNlLiBpZighZ2xvYmFsKSB7IC4uLn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZztcclxuIiwiLyoqXG4gKiBsb2Rhc2ggKEN1c3RvbSBCdWlsZCkgPGh0dHBzOi8vbG9kYXNoLmNvbS8+XG4gKiBCdWlsZDogYGxvZGFzaCBtb2R1bGFyaXplIGV4cG9ydHM9XCJucG1cIiAtbyAuL2BcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzIDxodHRwczovL2pxdWVyeS5vcmcvPlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICogQmFzZWQgb24gVW5kZXJzY29yZS5qcyAxLjguMyA8aHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvTElDRU5TRT5cbiAqIENvcHlyaWdodCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICovXG5cbi8qKiBVc2VkIGFzIHRoZSBgVHlwZUVycm9yYCBtZXNzYWdlIGZvciBcIkZ1bmN0aW9uc1wiIG1ldGhvZHMuICovXG52YXIgRlVOQ19FUlJPUl9URVhUID0gJ0V4cGVjdGVkIGEgZnVuY3Rpb24nO1xuXG4vKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB2YXJpb3VzIGBOdW1iZXJgIGNvbnN0YW50cy4gKi9cbnZhciBOQU4gPSAwIC8gMDtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nO1xuXG4vKiogVXNlZCB0byBtYXRjaCBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlLiAqL1xudmFyIHJlVHJpbSA9IC9eXFxzK3xcXHMrJC9nO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmFkIHNpZ25lZCBoZXhhZGVjaW1hbCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNCYWRIZXggPSAvXlstK10weFswLTlhLWZdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJpbmFyeSBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNCaW5hcnkgPSAvXjBiWzAxXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBvY3RhbCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlSXNPY3RhbCA9IC9eMG9bMC03XSskL2k7XG5cbi8qKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB3aXRob3V0IGEgZGVwZW5kZW5jeSBvbiBgcm9vdGAuICovXG52YXIgZnJlZVBhcnNlSW50ID0gcGFyc2VJbnQ7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMuICovXG52YXIgZnJlZUdsb2JhbCA9IHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsICYmIGdsb2JhbC5PYmplY3QgPT09IE9iamVjdCAmJiBnbG9iYWw7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgc2VsZmAuICovXG52YXIgZnJlZVNlbGYgPSB0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmICYmIHNlbGYuT2JqZWN0ID09PSBPYmplY3QgJiYgc2VsZjtcblxuLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG52YXIgcm9vdCA9IGZyZWVHbG9iYWwgfHwgZnJlZVNlbGYgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gKiBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9iamVjdFRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heCxcbiAgICBuYXRpdmVNaW4gPSBNYXRoLm1pbjtcblxuLyoqXG4gKiBHZXRzIHRoZSB0aW1lc3RhbXAgb2YgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2VcbiAqIHRoZSBVbml4IGVwb2NoICgxIEphbnVhcnkgMTk3MCAwMDowMDowMCBVVEMpLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMi40LjBcbiAqIEBjYXRlZ29yeSBEYXRlXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lc3RhbXAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uZGVmZXIoZnVuY3Rpb24oc3RhbXApIHtcbiAqICAgY29uc29sZS5sb2coXy5ub3coKSAtIHN0YW1wKTtcbiAqIH0sIF8ubm93KCkpO1xuICogLy8gPT4gTG9ncyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBpdCB0b29rIGZvciB0aGUgZGVmZXJyZWQgaW52b2NhdGlvbi5cbiAqL1xudmFyIG5vdyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcm9vdC5EYXRlLm5vdygpO1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVib3VuY2VkIGZ1bmN0aW9uIHRoYXQgZGVsYXlzIGludm9raW5nIGBmdW5jYCB1bnRpbCBhZnRlciBgd2FpdGBcbiAqIG1pbGxpc2Vjb25kcyBoYXZlIGVsYXBzZWQgc2luY2UgdGhlIGxhc3QgdGltZSB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHdhc1xuICogaW52b2tlZC4gVGhlIGRlYm91bmNlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGAgbWV0aG9kIHRvIGNhbmNlbFxuICogZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG8gaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uXG4gKiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYCBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGVcbiAqIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YCB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWRcbiAqIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnRcbiAqIGNhbGxzIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgXG4gKiBpbnZvY2F0aW9uLlxuICpcbiAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uXG4gKiBpcyBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gKlxuICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gKiB1bnRpbCB0byB0aGUgbmV4dCB0aWNrLCBzaW1pbGFyIHRvIGBzZXRUaW1lb3V0YCB3aXRoIGEgdGltZW91dCBvZiBgMGAuXG4gKlxuICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLmRlYm91bmNlYCBhbmQgYF8udGhyb3R0bGVgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVib3VuY2UuXG4gKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkuXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz1mYWxzZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMubWF4V2FpdF1cbiAqICBUaGUgbWF4aW11bSB0aW1lIGBmdW5jYCBpcyBhbGxvd2VkIHRvIGJlIGRlbGF5ZWQgYmVmb3JlIGl0J3MgaW52b2tlZC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZGVib3VuY2VkIGZ1bmN0aW9uLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBBdm9pZCBjb3N0bHkgY2FsY3VsYXRpb25zIHdoaWxlIHRoZSB3aW5kb3cgc2l6ZSBpcyBpbiBmbHV4LlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3Jlc2l6ZScsIF8uZGVib3VuY2UoY2FsY3VsYXRlTGF5b3V0LCAxNTApKTtcbiAqXG4gKiAvLyBJbnZva2UgYHNlbmRNYWlsYCB3aGVuIGNsaWNrZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxscy5cbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmRlYm91bmNlKHNlbmRNYWlsLCAzMDAsIHtcbiAqICAgJ2xlYWRpbmcnOiB0cnVlLFxuICogICAndHJhaWxpbmcnOiBmYWxzZVxuICogfSkpO1xuICpcbiAqIC8vIEVuc3VyZSBgYmF0Y2hMb2dgIGlzIGludm9rZWQgb25jZSBhZnRlciAxIHNlY29uZCBvZiBkZWJvdW5jZWQgY2FsbHMuXG4gKiB2YXIgZGVib3VuY2VkID0gXy5kZWJvdW5jZShiYXRjaExvZywgMjUwLCB7ICdtYXhXYWl0JzogMTAwMCB9KTtcbiAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAqIGpRdWVyeShzb3VyY2UpLm9uKCdtZXNzYWdlJywgZGVib3VuY2VkKTtcbiAqXG4gKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIGRlYm91bmNlZCBpbnZvY2F0aW9uLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgZGVib3VuY2VkLmNhbmNlbCk7XG4gKi9cbmZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgdmFyIGxhc3RBcmdzLFxuICAgICAgbGFzdFRoaXMsXG4gICAgICBtYXhXYWl0LFxuICAgICAgcmVzdWx0LFxuICAgICAgdGltZXJJZCxcbiAgICAgIGxhc3RDYWxsVGltZSxcbiAgICAgIGxhc3RJbnZva2VUaW1lID0gMCxcbiAgICAgIGxlYWRpbmcgPSBmYWxzZSxcbiAgICAgIG1heGluZyA9IGZhbHNlLFxuICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICB9XG4gIHdhaXQgPSB0b051bWJlcih3YWl0KSB8fCAwO1xuICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICBsZWFkaW5nID0gISFvcHRpb25zLmxlYWRpbmc7XG4gICAgbWF4aW5nID0gJ21heFdhaXQnIGluIG9wdGlvbnM7XG4gICAgbWF4V2FpdCA9IG1heGluZyA/IG5hdGl2ZU1heCh0b051bWJlcihvcHRpb25zLm1heFdhaXQpIHx8IDAsIHdhaXQpIDogbWF4V2FpdDtcbiAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICB9XG5cbiAgZnVuY3Rpb24gaW52b2tlRnVuYyh0aW1lKSB7XG4gICAgdmFyIGFyZ3MgPSBsYXN0QXJncyxcbiAgICAgICAgdGhpc0FyZyA9IGxhc3RUaGlzO1xuXG4gICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gbGVhZGluZ0VkZ2UodGltZSkge1xuICAgIC8vIFJlc2V0IGFueSBgbWF4V2FpdGAgdGltZXIuXG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIC8vIFN0YXJ0IHRoZSB0aW1lciBmb3IgdGhlIHRyYWlsaW5nIGVkZ2UuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAvLyBJbnZva2UgdGhlIGxlYWRpbmcgZWRnZS5cbiAgICByZXR1cm4gbGVhZGluZyA/IGludm9rZUZ1bmModGltZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiByZW1haW5pbmdXYWl0KHRpbWUpIHtcbiAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lLFxuICAgICAgICByZXN1bHQgPSB3YWl0IC0gdGltZVNpbmNlTGFzdENhbGw7XG5cbiAgICByZXR1cm4gbWF4aW5nID8gbmF0aXZlTWluKHJlc3VsdCwgbWF4V2FpdCAtIHRpbWVTaW5jZUxhc3RJbnZva2UpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gc2hvdWxkSW52b2tlKHRpbWUpIHtcbiAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lO1xuXG4gICAgLy8gRWl0aGVyIHRoaXMgaXMgdGhlIGZpcnN0IGNhbGwsIGFjdGl2aXR5IGhhcyBzdG9wcGVkIGFuZCB3ZSdyZSBhdCB0aGVcbiAgICAvLyB0cmFpbGluZyBlZGdlLCB0aGUgc3lzdGVtIHRpbWUgaGFzIGdvbmUgYmFja3dhcmRzIGFuZCB3ZSdyZSB0cmVhdGluZ1xuICAgIC8vIGl0IGFzIHRoZSB0cmFpbGluZyBlZGdlLCBvciB3ZSd2ZSBoaXQgdGhlIGBtYXhXYWl0YCBsaW1pdC5cbiAgICByZXR1cm4gKGxhc3RDYWxsVGltZSA9PT0gdW5kZWZpbmVkIHx8ICh0aW1lU2luY2VMYXN0Q2FsbCA+PSB3YWl0KSB8fFxuICAgICAgKHRpbWVTaW5jZUxhc3RDYWxsIDwgMCkgfHwgKG1heGluZyAmJiB0aW1lU2luY2VMYXN0SW52b2tlID49IG1heFdhaXQpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRpbWVyRXhwaXJlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpO1xuICAgIGlmIChzaG91bGRJbnZva2UodGltZSkpIHtcbiAgICAgIHJldHVybiB0cmFpbGluZ0VkZ2UodGltZSk7XG4gICAgfVxuICAgIC8vIFJlc3RhcnQgdGhlIHRpbWVyLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgcmVtYWluaW5nV2FpdCh0aW1lKSk7XG4gIH1cblxuICBmdW5jdGlvbiB0cmFpbGluZ0VkZ2UodGltZSkge1xuICAgIHRpbWVySWQgPSB1bmRlZmluZWQ7XG5cbiAgICAvLyBPbmx5IGludm9rZSBpZiB3ZSBoYXZlIGBsYXN0QXJnc2Agd2hpY2ggbWVhbnMgYGZ1bmNgIGhhcyBiZWVuXG4gICAgLy8gZGVib3VuY2VkIGF0IGxlYXN0IG9uY2UuXG4gICAgaWYgKHRyYWlsaW5nICYmIGxhc3RBcmdzKSB7XG4gICAgICByZXR1cm4gaW52b2tlRnVuYyh0aW1lKTtcbiAgICB9XG4gICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgIGlmICh0aW1lcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICB9XG4gICAgbGFzdEludm9rZVRpbWUgPSAwO1xuICAgIGxhc3RBcmdzID0gbGFzdENhbGxUaW1lID0gbGFzdFRoaXMgPSB0aW1lcklkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgcmV0dXJuIHRpbWVySWQgPT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IHRyYWlsaW5nRWRnZShub3coKSk7XG4gIH1cblxuICBmdW5jdGlvbiBkZWJvdW5jZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKSxcbiAgICAgICAgaXNJbnZva2luZyA9IHNob3VsZEludm9rZSh0aW1lKTtcblxuICAgIGxhc3RBcmdzID0gYXJndW1lbnRzO1xuICAgIGxhc3RUaGlzID0gdGhpcztcbiAgICBsYXN0Q2FsbFRpbWUgPSB0aW1lO1xuXG4gICAgaWYgKGlzSW52b2tpbmcpIHtcbiAgICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGxlYWRpbmdFZGdlKGxhc3RDYWxsVGltZSk7XG4gICAgICB9XG4gICAgICBpZiAobWF4aW5nKSB7XG4gICAgICAgIC8vIEhhbmRsZSBpbnZvY2F0aW9ucyBpbiBhIHRpZ2h0IGxvb3AuXG4gICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgICAgIHJldHVybiBpbnZva2VGdW5jKGxhc3RDYWxsVGltZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgZGVib3VuY2VkLmNhbmNlbCA9IGNhbmNlbDtcbiAgZGVib3VuY2VkLmZsdXNoID0gZmx1c2g7XG4gIHJldHVybiBkZWJvdW5jZWQ7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHRocm90dGxlZCBmdW5jdGlvbiB0aGF0IG9ubHkgaW52b2tlcyBgZnVuY2AgYXQgbW9zdCBvbmNlIHBlclxuICogZXZlcnkgYHdhaXRgIG1pbGxpc2Vjb25kcy4gVGhlIHRocm90dGxlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGBcbiAqIG1ldGhvZCB0byBjYW5jZWwgZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG9cbiAqIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYFxuICogc2hvdWxkIGJlIGludm9rZWQgb24gdGhlIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YFxuICogdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZVxuICogdGhyb3R0bGVkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50IGNhbGxzIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJuIHRoZVxuICogcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYCBpbnZvY2F0aW9uLlxuICpcbiAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uXG4gKiBpcyBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gKlxuICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gKiB1bnRpbCB0byB0aGUgbmV4dCB0aWNrLCBzaW1pbGFyIHRvIGBzZXRUaW1lb3V0YCB3aXRoIGEgdGltZW91dCBvZiBgMGAuXG4gKlxuICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLnRocm90dGxlYCBhbmQgYF8uZGVib3VuY2VgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gdGhyb3R0bGUuXG4gKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gdGhyb3R0bGUgaW52b2NhdGlvbnMgdG8uXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBBdm9pZCBleGNlc3NpdmVseSB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgc2Nyb2xsaW5nLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCkpO1xuICpcbiAqIC8vIEludm9rZSBgcmVuZXdUb2tlbmAgd2hlbiB0aGUgY2xpY2sgZXZlbnQgaXMgZmlyZWQsIGJ1dCBub3QgbW9yZSB0aGFuIG9uY2UgZXZlcnkgNSBtaW51dGVzLlxuICogdmFyIHRocm90dGxlZCA9IF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7ICd0cmFpbGluZyc6IGZhbHNlIH0pO1xuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIHRocm90dGxlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyB0aHJvdHRsZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIHRocm90dGxlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiB0aHJvdHRsZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsZWFkaW5nID0gdHJ1ZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICBsZWFkaW5nID0gJ2xlYWRpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMubGVhZGluZyA6IGxlYWRpbmc7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuICByZXR1cm4gZGVib3VuY2UoZnVuYywgd2FpdCwge1xuICAgICdsZWFkaW5nJzogbGVhZGluZyxcbiAgICAnbWF4V2FpdCc6IHdhaXQsXG4gICAgJ3RyYWlsaW5nJzogdHJhaWxpbmdcbiAgfSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgdGhlXG4gKiBbbGFuZ3VhZ2UgdHlwZV0oaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWVjbWFzY3JpcHQtbGFuZ3VhZ2UtdHlwZXMpXG4gKiBvZiBgT2JqZWN0YC4gKGUuZy4gYXJyYXlzLCBmdW5jdGlvbnMsIG9iamVjdHMsIHJlZ2V4ZXMsIGBuZXcgTnVtYmVyKDApYCwgYW5kIGBuZXcgU3RyaW5nKCcnKWApXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNPYmplY3Qoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KF8ubm9vcCk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICByZXR1cm4gISF2YWx1ZSAmJiAodHlwZSA9PSAnb2JqZWN0JyB8fCB0eXBlID09ICdmdW5jdGlvbicpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLiBBIHZhbHVlIGlzIG9iamVjdC1saWtlIGlmIGl0J3Mgbm90IGBudWxsYFxuICogYW5kIGhhcyBhIGB0eXBlb2ZgIHJlc3VsdCBvZiBcIm9iamVjdFwiLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKF8ubm9vcCk7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3RMaWtlKHZhbHVlKSB7XG4gIHJldHVybiAhIXZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0Jztcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN5bWJvbGAgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHN5bWJvbCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzU3ltYm9sKFN5bWJvbC5pdGVyYXRvcik7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1N5bWJvbCgnYWJjJyk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc1N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdzeW1ib2wnIHx8XG4gICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gc3ltYm9sVGFnKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgbnVtYmVyLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgbnVtYmVyLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLnRvTnVtYmVyKDMuMik7XG4gKiAvLyA9PiAzLjJcbiAqXG4gKiBfLnRvTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICogLy8gPT4gNWUtMzI0XG4gKlxuICogXy50b051bWJlcihJbmZpbml0eSk7XG4gKiAvLyA9PiBJbmZpbml0eVxuICpcbiAqIF8udG9OdW1iZXIoJzMuMicpO1xuICogLy8gPT4gMy4yXG4gKi9cbmZ1bmN0aW9uIHRvTnVtYmVyKHZhbHVlKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgIHJldHVybiBOQU47XG4gIH1cbiAgaWYgKGlzT2JqZWN0KHZhbHVlKSkge1xuICAgIHZhciBvdGhlciA9IHR5cGVvZiB2YWx1ZS52YWx1ZU9mID09ICdmdW5jdGlvbicgPyB2YWx1ZS52YWx1ZU9mKCkgOiB2YWx1ZTtcbiAgICB2YWx1ZSA9IGlzT2JqZWN0KG90aGVyKSA/IChvdGhlciArICcnKSA6IG90aGVyO1xuICB9XG4gIGlmICh0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6ICt2YWx1ZTtcbiAgfVxuICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UocmVUcmltLCAnJyk7XG4gIHZhciBpc0JpbmFyeSA9IHJlSXNCaW5hcnkudGVzdCh2YWx1ZSk7XG4gIHJldHVybiAoaXNCaW5hcnkgfHwgcmVJc09jdGFsLnRlc3QodmFsdWUpKVxuICAgID8gZnJlZVBhcnNlSW50KHZhbHVlLnNsaWNlKDIpLCBpc0JpbmFyeSA/IDIgOiA4KVxuICAgIDogKHJlSXNCYWRIZXgudGVzdCh2YWx1ZSkgPyBOQU4gOiArdmFsdWUpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRocm90dGxlO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHNldHRpbmdzXzEgPSByZXF1aXJlKFwiLi9zZXR0aW5nc1wiKTtcbmV4cG9ydHMuY3JlYXRlUG9zdGVyRm9yVnNDb2RlID0gKHZzY29kZSkgPT4ge1xuICAgIHJldHVybiBuZXcgY2xhc3Mge1xuICAgICAgICBwb3N0TWVzc2FnZSh0eXBlLCBib2R5KSB7XG4gICAgICAgICAgICB2c2NvZGUucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgICAgc291cmNlOiBzZXR0aW5nc18xLmdldFNldHRpbmdzKCkuc291cmNlLFxuICAgICAgICAgICAgICAgIGJvZHlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZnVuY3Rpb24gb25jZURvY3VtZW50TG9hZGVkKGYpIHtcbiAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnIHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICd1bmluaXRpYWxpemVkJykge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmKCk7XG4gICAgfVxufVxuZXhwb3J0cy5vbmNlRG9jdW1lbnRMb2FkZWQgPSBvbmNlRG9jdW1lbnRMb2FkZWQ7XG4iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuY29uc3Qgc2Nyb2xsX3N5bmNfMSA9IHJlcXVpcmUoXCIuL3Njcm9sbC1zeW5jXCIpO1xuY2xhc3MgQWN0aXZlTGluZU1hcmtlciB7XG4gICAgb25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uKGxpbmUpIHtcbiAgICAgICAgY29uc3QgeyBwcmV2aW91cyB9ID0gc2Nyb2xsX3N5bmNfMS5nZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZShwcmV2aW91cyAmJiBwcmV2aW91cy5lbGVtZW50KTtcbiAgICB9XG4gICAgX3VwZGF0ZShiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5fdW5tYXJrQWN0aXZlRWxlbWVudCh0aGlzLl9jdXJyZW50KTtcbiAgICAgICAgdGhpcy5fbWFya0FjdGl2ZUVsZW1lbnQoYmVmb3JlKTtcbiAgICAgICAgdGhpcy5fY3VycmVudCA9IGJlZm9yZTtcbiAgICB9XG4gICAgX3VubWFya0FjdGl2ZUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lLnJlcGxhY2UoL1xcYmNvZGUtYWN0aXZlLWxpbmVcXGIvZywgJycpO1xuICAgIH1cbiAgICBfbWFya0FjdGl2ZUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSArPSAnIGNvZGUtYWN0aXZlLWxpbmUnO1xuICAgIH1cbn1cbmV4cG9ydHMuQWN0aXZlTGluZU1hcmtlciA9IEFjdGl2ZUxpbmVNYXJrZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgYWN0aXZlTGluZU1hcmtlcl8xID0gcmVxdWlyZShcIi4vYWN0aXZlTGluZU1hcmtlclwiKTtcbmNvbnN0IGV2ZW50c18xID0gcmVxdWlyZShcIi4vZXZlbnRzXCIpO1xuY29uc3QgbWVzc2FnaW5nXzEgPSByZXF1aXJlKFwiLi9tZXNzYWdpbmdcIik7XG5jb25zdCBzY3JvbGxfc3luY18xID0gcmVxdWlyZShcIi4vc2Nyb2xsLXN5bmNcIik7XG5jb25zdCBzZXR0aW5nc18xID0gcmVxdWlyZShcIi4vc2V0dGluZ3NcIik7XG5jb25zdCB0aHJvdHRsZSA9IHJlcXVpcmUoXCJsb2Rhc2gudGhyb3R0bGVcIik7XG5sZXQgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuY29uc3QgbWFya2VyID0gbmV3IGFjdGl2ZUxpbmVNYXJrZXJfMS5BY3RpdmVMaW5lTWFya2VyKCk7XG5jb25zdCBzZXR0aW5ncyA9IHNldHRpbmdzXzEuZ2V0U2V0dGluZ3MoKTtcbmNvbnN0IHZzY29kZSA9IGFjcXVpcmVWc0NvZGVBcGkoKTtcbi8vIFNldCBWUyBDb2RlIHN0YXRlXG5sZXQgc3RhdGUgPSBzZXR0aW5nc18xLmdldERhdGEoJ2RhdGEtc3RhdGUnKTtcbnZzY29kZS5zZXRTdGF0ZShzdGF0ZSk7XG5jb25zdCBtZXNzYWdpbmcgPSBtZXNzYWdpbmdfMS5jcmVhdGVQb3N0ZXJGb3JWc0NvZGUodnNjb2RlKTtcbndpbmRvdy5jc3BBbGVydGVyLnNldFBvc3RlcihtZXNzYWdpbmcpO1xud2luZG93LnN0eWxlTG9hZGluZ01vbml0b3Iuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG53aW5kb3cub25sb2FkID0gKCkgPT4ge1xuICAgIHVwZGF0ZUltYWdlU2l6ZXMoKTtcbn07XG5ldmVudHNfMS5vbmNlRG9jdW1lbnRMb2FkZWQoKCkgPT4ge1xuICAgIGlmIChzZXR0aW5ncy5zY3JvbGxQcmV2aWV3V2l0aEVkaXRvcikge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBzY3JvbGwgdG8gZnJhZ21lbnQgaWYgYXZhaWxhYmxlXG4gICAgICAgICAgICBpZiAoc3RhdGUuZnJhZ21lbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gc2Nyb2xsX3N5bmNfMS5nZXRMaW5lRWxlbWVudEZvckZyYWdtZW50KHN0YXRlLmZyYWdtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGVsZW1lbnQubGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW5pdGlhbExpbmUgPSArc2V0dGluZ3MubGluZTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTmFOKGluaXRpYWxMaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbF9zeW5jXzEuc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGluaXRpYWxMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDApO1xuICAgIH1cbn0pO1xuY29uc3Qgb25VcGRhdGVWaWV3ID0gKCgpID0+IHtcbiAgICBjb25zdCBkb1Njcm9sbCA9IHRocm90dGxlKChsaW5lKSA9PiB7XG4gICAgICAgIHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgc2Nyb2xsX3N5bmNfMS5zY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSk7XG4gICAgfSwgNTApO1xuICAgIHJldHVybiAobGluZSwgc2V0dGluZ3MpID0+IHtcbiAgICAgICAgaWYgKCFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgc2V0dGluZ3MubGluZSA9IGxpbmU7XG4gICAgICAgICAgICBkb1Njcm9sbChsaW5lKTtcbiAgICAgICAgfVxuICAgIH07XG59KSgpO1xubGV0IHVwZGF0ZUltYWdlU2l6ZXMgPSB0aHJvdHRsZSgoKSA9PiB7XG4gICAgY29uc3QgaW1hZ2VJbmZvID0gW107XG4gICAgbGV0IGltYWdlcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbWcnKTtcbiAgICBpZiAoaW1hZ2VzKSB7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpbWcgPSBpbWFnZXNbaV07XG4gICAgICAgICAgICBpZiAoaW1nLmNsYXNzTGlzdC5jb250YWlucygnbG9hZGluZycpKSB7XG4gICAgICAgICAgICAgICAgaW1nLmNsYXNzTGlzdC5yZW1vdmUoJ2xvYWRpbmcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGltYWdlSW5mby5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogaW1nLmlkLFxuICAgICAgICAgICAgICAgIGhlaWdodDogaW1nLmhlaWdodCxcbiAgICAgICAgICAgICAgICB3aWR0aDogaW1nLndpZHRoXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NhY2hlSW1hZ2VTaXplcycsIGltYWdlSW5mbyk7XG4gICAgfVxufSwgNTApO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHtcbiAgICBzY3JvbGxEaXNhYmxlZCA9IHRydWU7XG4gICAgdXBkYXRlSW1hZ2VTaXplcygpO1xufSwgdHJ1ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGV2ZW50ID0+IHtcbiAgICBpZiAoZXZlbnQuZGF0YS5zb3VyY2UgIT09IHNldHRpbmdzLnNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHN3aXRjaCAoZXZlbnQuZGF0YS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ29uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbic6XG4gICAgICAgICAgICBtYXJrZXIub25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uKGV2ZW50LmRhdGEubGluZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndXBkYXRlVmlldyc6XG4gICAgICAgICAgICBvblVwZGF0ZVZpZXcoZXZlbnQuZGF0YS5saW5lLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59LCBmYWxzZSk7XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGV2ZW50ID0+IHtcbiAgICBpZiAoIXNldHRpbmdzLmRvdWJsZUNsaWNrVG9Td2l0Y2hUb0VkaXRvcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIElnbm9yZSBjbGlja3Mgb24gbGlua3NcbiAgICBmb3IgKGxldCBub2RlID0gZXZlbnQudGFyZ2V0OyBub2RlOyBub2RlID0gbm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgIGlmIChub2RlLnRhZ05hbWUgPT09ICdBJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IG9mZnNldCA9IGV2ZW50LnBhZ2VZO1xuICAgIGNvbnN0IGxpbmUgPSBzY3JvbGxfc3luY18xLmdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCk7XG4gICAgaWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcbiAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdkaWRDbGljaycsIHsgbGluZTogTWF0aC5mbG9vcihsaW5lKSB9KTtcbiAgICB9XG59KTtcbmNvbnN0IHBhc3NUaHJvdWdoTGlua1NjaGVtZXMgPSBbJ2h0dHA6JywgJ2h0dHBzOicsICdtYWlsdG86JywgJ3ZzY29kZTonLCAndnNjb2RlLWluc2lkZXJzJ107XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGV2ZW50ID0+IHtcbiAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IG5vZGUgPSBldmVudC50YXJnZXQ7XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUudGFnTmFtZSAmJiBub2RlLnRhZ05hbWUgPT09ICdBJyAmJiBub2RlLmhyZWYpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFBhc3MgdGhyb3VnaCBrbm93biBzY2hlbWVzXG4gICAgICAgICAgICBpZiAocGFzc1Rocm91Z2hMaW5rU2NoZW1lcy5zb21lKHNjaGVtZSA9PiBub2RlLmhyZWYuc3RhcnRzV2l0aChzY2hlbWUpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGhyZWZUZXh0ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtaHJlZicpIHx8IG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJyk7XG4gICAgICAgICAgICAvLyBJZiBvcmlnaW5hbCBsaW5rIGRvZXNuJ3QgbG9vayBsaWtlIGEgdXJsLCBkZWxlZ2F0ZSBiYWNrIHRvIFZTIENvZGUgdG8gcmVzb2x2ZVxuICAgICAgICAgICAgaWYgKCEvXlthLXpcXC1dKzovaS50ZXN0KGhyZWZUZXh0KSkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnb3BlbkxpbmsnLCB7IGhyZWY6IGhyZWZUZXh0IH0pO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgfVxufSwgdHJ1ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhyb3R0bGUoKCkgPT4ge1xuICAgIGlmIChzY3JvbGxEaXNhYmxlZCkge1xuICAgICAgICBzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgbGluZSA9IHNjcm9sbF9zeW5jXzEuZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuICAgICAgICBpZiAodHlwZW9mIGxpbmUgPT09ICdudW1iZXInICYmICFpc05hTihsaW5lKSkge1xuICAgICAgICAgICAgbWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdyZXZlYWxMaW5lJywgeyBsaW5lIH0pO1xuICAgICAgICAgICAgc3RhdGUubGluZSA9IGxpbmU7XG4gICAgICAgICAgICB2c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxufSwgNTApKTtcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/extensions/markdown-language-features/media/pre.js b/extensions/markdown-language-features/media/pre.js index 5c9c7fb3b8b..28098246c05 100644 --- a/extensions/markdown-language-features/media/pre.js +++ b/extensions/markdown-language-features/media/pre.js @@ -1,280 +1,2 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./preview-src/pre.ts"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./preview-src/csp.ts": -/*!****************************!*\ - !*** ./preview-src/csp.ts ***! - \****************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const settings_1 = __webpack_require__(/*! ./settings */ "./preview-src/settings.ts"); -const strings_1 = __webpack_require__(/*! ./strings */ "./preview-src/strings.ts"); -/** - * Shows an alert when there is a content security policy violation. - */ -class CspAlerter { - constructor() { - this.didShow = false; - this.didHaveCspWarning = false; - document.addEventListener('securitypolicyviolation', () => { - this.onCspWarning(); - }); - window.addEventListener('message', (event) => { - if (event && event.data && event.data.name === 'vscode-did-block-svg') { - this.onCspWarning(); - } - }); - } - setPoster(poster) { - this.messaging = poster; - if (this.didHaveCspWarning) { - this.showCspWarning(); - } - } - onCspWarning() { - this.didHaveCspWarning = true; - this.showCspWarning(); - } - showCspWarning() { - const strings = strings_1.getStrings(); - const settings = settings_1.getSettings(); - if (this.didShow || settings.disableSecurityWarnings || !this.messaging) { - return; - } - this.didShow = true; - const notification = document.createElement('a'); - notification.innerText = strings.cspAlertMessageText; - notification.setAttribute('id', 'code-csp-warning'); - notification.setAttribute('title', strings.cspAlertMessageTitle); - notification.setAttribute('role', 'button'); - notification.setAttribute('aria-label', strings.cspAlertMessageLabel); - notification.onclick = () => { - this.messaging.postMessage('showPreviewSecuritySelector', { source: settings.source }); - }; - document.body.appendChild(notification); - } -} -exports.CspAlerter = CspAlerter; - - -/***/ }), - -/***/ "./preview-src/loading.ts": -/*!********************************!*\ - !*** ./preview-src/loading.ts ***! - \********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -class StyleLoadingMonitor { - constructor() { - this.unloadedStyles = []; - this.finishedLoading = false; - const onStyleLoadError = (event) => { - const source = event.target.dataset.source; - this.unloadedStyles.push(source); - }; - window.addEventListener('DOMContentLoaded', () => { - for (const link of document.getElementsByClassName('code-user-style')) { - if (link.dataset.source) { - link.onerror = onStyleLoadError; - } - } - }); - window.addEventListener('load', () => { - if (!this.unloadedStyles.length) { - return; - } - this.finishedLoading = true; - if (this.poster) { - this.poster.postMessage('previewStyleLoadError', { unloadedStyles: this.unloadedStyles }); - } - }); - } - setPoster(poster) { - this.poster = poster; - if (this.finishedLoading) { - poster.postMessage('previewStyleLoadError', { unloadedStyles: this.unloadedStyles }); - } - } -} -exports.StyleLoadingMonitor = StyleLoadingMonitor; - - -/***/ }), - -/***/ "./preview-src/pre.ts": -/*!****************************!*\ - !*** ./preview-src/pre.ts ***! - \****************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const csp_1 = __webpack_require__(/*! ./csp */ "./preview-src/csp.ts"); -const loading_1 = __webpack_require__(/*! ./loading */ "./preview-src/loading.ts"); -window.cspAlerter = new csp_1.CspAlerter(); -window.styleLoadingMonitor = new loading_1.StyleLoadingMonitor(); - - -/***/ }), - -/***/ "./preview-src/settings.ts": -/*!*********************************!*\ - !*** ./preview-src/settings.ts ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -let cachedSettings = undefined; -function getData(key) { - const element = document.getElementById('vscode-markdown-preview-data'); - if (element) { - const data = element.getAttribute(key); - if (data) { - return JSON.parse(data); - } - } - throw new Error(`Could not load data for ${key}`); -} -exports.getData = getData; -function getSettings() { - if (cachedSettings) { - return cachedSettings; - } - cachedSettings = getData('data-settings'); - if (cachedSettings) { - return cachedSettings; - } - throw new Error('Could not load settings'); -} -exports.getSettings = getSettings; - - -/***/ }), - -/***/ "./preview-src/strings.ts": -/*!********************************!*\ - !*** ./preview-src/strings.ts ***! - \********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -function getStrings() { - const store = document.getElementById('vscode-markdown-preview-data'); - if (store) { - const data = store.getAttribute('data-strings'); - if (data) { - return JSON.parse(data); - } - } - throw new Error('Could not load strings'); -} -exports.getStrings = getStrings; - - -/***/ }) - -/******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvY3NwLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2xvYWRpbmcudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvcHJlLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3NldHRpbmdzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3N0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseURBQWlELGNBQWM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7OztBQUdBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxjQUFjO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1RUFBdUUsMEJBQTBCO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNyREE7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtFQUFrRSxzQ0FBc0M7QUFDeEc7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQsc0NBQXNDO0FBQy9GO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsY0FBYztBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsSUFBSTtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJwcmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9wcmV2aWV3LXNyYy9wcmUudHNcIik7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuY29uc3Qgc3RyaW5nc18xID0gcmVxdWlyZShcIi4vc3RyaW5nc1wiKTtcbi8qKlxuICogU2hvd3MgYW4gYWxlcnQgd2hlbiB0aGVyZSBpcyBhIGNvbnRlbnQgc2VjdXJpdHkgcG9saWN5IHZpb2xhdGlvbi5cbiAqL1xuY2xhc3MgQ3NwQWxlcnRlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZGlkU2hvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRpZEhhdmVDc3BXYXJuaW5nID0gZmFsc2U7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3NlY3VyaXR5cG9saWN5dmlvbGF0aW9uJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vbkNzcFdhcm5pbmcoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQgJiYgZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhLm5hbWUgPT09ICd2c2NvZGUtZGlkLWJsb2NrLXN2ZycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ3NwV2FybmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2V0UG9zdGVyKHBvc3Rlcikge1xuICAgICAgICB0aGlzLm1lc3NhZ2luZyA9IHBvc3RlcjtcbiAgICAgICAgaWYgKHRoaXMuZGlkSGF2ZUNzcFdhcm5pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0NzcFdhcm5pbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBvbkNzcFdhcm5pbmcoKSB7XG4gICAgICAgIHRoaXMuZGlkSGF2ZUNzcFdhcm5pbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLnNob3dDc3BXYXJuaW5nKCk7XG4gICAgfVxuICAgIHNob3dDc3BXYXJuaW5nKCkge1xuICAgICAgICBjb25zdCBzdHJpbmdzID0gc3RyaW5nc18xLmdldFN0cmluZ3MoKTtcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBzZXR0aW5nc18xLmdldFNldHRpbmdzKCk7XG4gICAgICAgIGlmICh0aGlzLmRpZFNob3cgfHwgc2V0dGluZ3MuZGlzYWJsZVNlY3VyaXR5V2FybmluZ3MgfHwgIXRoaXMubWVzc2FnaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaWRTaG93ID0gdHJ1ZTtcbiAgICAgICAgY29uc3Qgbm90aWZpY2F0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICBub3RpZmljYXRpb24uaW5uZXJUZXh0ID0gc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VUZXh0O1xuICAgICAgICBub3RpZmljYXRpb24uc2V0QXR0cmlidXRlKCdpZCcsICdjb2RlLWNzcC13YXJuaW5nJyk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VUaXRsZSk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnYnV0dG9uJyk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBzdHJpbmdzLmNzcEFsZXJ0TWVzc2FnZUxhYmVsKTtcbiAgICAgICAgbm90aWZpY2F0aW9uLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnc2hvd1ByZXZpZXdTZWN1cml0eVNlbGVjdG9yJywgeyBzb3VyY2U6IHNldHRpbmdzLnNvdXJjZSB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChub3RpZmljYXRpb24pO1xuICAgIH1cbn1cbmV4cG9ydHMuQ3NwQWxlcnRlciA9IENzcEFsZXJ0ZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNsYXNzIFN0eWxlTG9hZGluZ01vbml0b3Ige1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnVubG9hZGVkU3R5bGVzID0gW107XG4gICAgICAgIHRoaXMuZmluaXNoZWRMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IG9uU3R5bGVMb2FkRXJyb3IgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IGV2ZW50LnRhcmdldC5kYXRhc2V0LnNvdXJjZTtcbiAgICAgICAgICAgIHRoaXMudW5sb2FkZWRTdHlsZXMucHVzaChzb3VyY2UpO1xuICAgICAgICB9O1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbGluayBvZiBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdjb2RlLXVzZXItc3R5bGUnKSkge1xuICAgICAgICAgICAgICAgIGlmIChsaW5rLmRhdGFzZXQuc291cmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmsub25lcnJvciA9IG9uU3R5bGVMb2FkRXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMudW5sb2FkZWRTdHlsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5maW5pc2hlZExvYWRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zdGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3N0ZXIucG9zdE1lc3NhZ2UoJ3ByZXZpZXdTdHlsZUxvYWRFcnJvcicsIHsgdW5sb2FkZWRTdHlsZXM6IHRoaXMudW5sb2FkZWRTdHlsZXMgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzZXRQb3N0ZXIocG9zdGVyKSB7XG4gICAgICAgIHRoaXMucG9zdGVyID0gcG9zdGVyO1xuICAgICAgICBpZiAodGhpcy5maW5pc2hlZExvYWRpbmcpIHtcbiAgICAgICAgICAgIHBvc3Rlci5wb3N0TWVzc2FnZSgncHJldmlld1N0eWxlTG9hZEVycm9yJywgeyB1bmxvYWRlZFN0eWxlczogdGhpcy51bmxvYWRlZFN0eWxlcyB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmV4cG9ydHMuU3R5bGVMb2FkaW5nTW9uaXRvciA9IFN0eWxlTG9hZGluZ01vbml0b3I7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY3NwXzEgPSByZXF1aXJlKFwiLi9jc3BcIik7XG5jb25zdCBsb2FkaW5nXzEgPSByZXF1aXJlKFwiLi9sb2FkaW5nXCIpO1xud2luZG93LmNzcEFsZXJ0ZXIgPSBuZXcgY3NwXzEuQ3NwQWxlcnRlcigpO1xud2luZG93LnN0eWxlTG9hZGluZ01vbml0b3IgPSBuZXcgbG9hZGluZ18xLlN0eWxlTG9hZGluZ01vbml0b3IoKTtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sZXQgY2FjaGVkU2V0dGluZ3MgPSB1bmRlZmluZWQ7XG5mdW5jdGlvbiBnZXREYXRhKGtleSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndnNjb2RlLW1hcmtkb3duLXByZXZpZXctZGF0YScpO1xuICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBkYXRhIGZvciAke2tleX1gKTtcbn1cbmV4cG9ydHMuZ2V0RGF0YSA9IGdldERhdGE7XG5mdW5jdGlvbiBnZXRTZXR0aW5ncygpIHtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICBjYWNoZWRTZXR0aW5ncyA9IGdldERhdGEoJ2RhdGEtc2V0dGluZ3MnKTtcbiAgICBpZiAoY2FjaGVkU2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHNldHRpbmdzJyk7XG59XG5leHBvcnRzLmdldFNldHRpbmdzID0gZ2V0U2V0dGluZ3M7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZnVuY3Rpb24gZ2V0U3RyaW5ncygpIHtcbiAgICBjb25zdCBzdG9yZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKHN0b3JlKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBzdG9yZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtc3RyaW5ncycpO1xuICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgbG9hZCBzdHJpbmdzJyk7XG59XG5leHBvcnRzLmdldFN0cmluZ3MgPSBnZXRTdHJpbmdzO1xuIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file +!function(e){var t={};function s(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,s),o.l=!0,o.exports}s.m=e,s.c=t,s.d=function(e,t,n){s.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},s.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,"a",t),t},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s.p="",s(s.s=5)}([function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});let n=void 0;function o(e){const t=document.getElementById("vscode-markdown-preview-data");if(t){const s=t.getAttribute(e);if(s)return JSON.parse(s)}throw new Error(`Could not load data for ${e}`)}t.getData=o,t.getSettings=function(){if(n)return n;if(n=o("data-settings"))return n;throw new Error("Could not load settings")}},,function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.StyleLoadingMonitor=class{constructor(){this.unloadedStyles=[],this.finishedLoading=!1;const e=e=>{const t=e.target.dataset.source;this.unloadedStyles.push(t)};window.addEventListener("DOMContentLoaded",()=>{for(const t of document.getElementsByClassName("code-user-style"))t.dataset.source&&(t.onerror=e)}),window.addEventListener("load",()=>{this.unloadedStyles.length&&(this.finishedLoading=!0,this.poster&&this.poster.postMessage("previewStyleLoadError",{unloadedStyles:this.unloadedStyles}))})}setPoster(e){this.poster=e,this.finishedLoading&&e.postMessage("previewStyleLoadError",{unloadedStyles:this.unloadedStyles})}}},function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getStrings=function(){const e=document.getElementById("vscode-markdown-preview-data");if(e){const t=e.getAttribute("data-strings");if(t)return JSON.parse(t)}throw new Error("Could not load strings")}},function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=s(0),o=s(3);t.CspAlerter=class{constructor(){this.didShow=!1,this.didHaveCspWarning=!1,document.addEventListener("securitypolicyviolation",()=>{this.onCspWarning()}),window.addEventListener("message",e=>{e&&e.data&&"vscode-did-block-svg"===e.data.name&&this.onCspWarning()})}setPoster(e){this.messaging=e,this.didHaveCspWarning&&this.showCspWarning()}onCspWarning(){this.didHaveCspWarning=!0,this.showCspWarning()}showCspWarning(){const e=o.getStrings(),t=n.getSettings();if(this.didShow||t.disableSecurityWarnings||!this.messaging)return;this.didShow=!0;const s=document.createElement("a");s.innerText=e.cspAlertMessageText,s.setAttribute("id","code-csp-warning"),s.setAttribute("title",e.cspAlertMessageTitle),s.setAttribute("role","button"),s.setAttribute("aria-label",e.cspAlertMessageLabel),s.onclick=(()=>{this.messaging.postMessage("showPreviewSecuritySelector",{source:t.source})}),document.body.appendChild(s)}}},function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=s(4),o=s(2);window.cspAlerter=new n.CspAlerter,window.styleLoadingMonitor=new o.StyleLoadingMonitor}]); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvc2V0dGluZ3MudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvbG9hZGluZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zdHJpbmdzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2NzcC50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9wcmUudHMiXSwibmFtZXMiOlsiaW5zdGFsbGVkTW9kdWxlcyIsIl9fd2VicGFja19yZXF1aXJlX18iLCJtb2R1bGVJZCIsImV4cG9ydHMiLCJtb2R1bGUiLCJpIiwibCIsIm1vZHVsZXMiLCJjYWxsIiwibSIsImMiLCJkIiwibmFtZSIsImdldHRlciIsIm8iLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImNvbmZpZ3VyYWJsZSIsImVudW1lcmFibGUiLCJnZXQiLCJyIiwidmFsdWUiLCJuIiwiX19lc01vZHVsZSIsIm9iamVjdCIsInByb3BlcnR5IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJwIiwicyIsImNhY2hlZFNldHRpbmdzIiwidW5kZWZpbmVkIiwiZ2V0RGF0YSIsImtleSIsImVsZW1lbnQiLCJkb2N1bWVudCIsImdldEVsZW1lbnRCeUlkIiwiZGF0YSIsImdldEF0dHJpYnV0ZSIsIkpTT04iLCJwYXJzZSIsIkVycm9yIiwiZ2V0U2V0dGluZ3MiLCJTdHlsZUxvYWRpbmdNb25pdG9yIiwiW29iamVjdCBPYmplY3RdIiwidGhpcyIsInVubG9hZGVkU3R5bGVzIiwiZmluaXNoZWRMb2FkaW5nIiwib25TdHlsZUxvYWRFcnJvciIsImV2ZW50Iiwic291cmNlIiwidGFyZ2V0IiwiZGF0YXNldCIsInB1c2giLCJ3aW5kb3ciLCJhZGRFdmVudExpc3RlbmVyIiwibGluayIsImdldEVsZW1lbnRzQnlDbGFzc05hbWUiLCJvbmVycm9yIiwibGVuZ3RoIiwicG9zdGVyIiwicG9zdE1lc3NhZ2UiLCJnZXRTdHJpbmdzIiwic3RvcmUiLCJzZXR0aW5nc18xIiwic3RyaW5nc18xIiwiQ3NwQWxlcnRlciIsImRpZFNob3ciLCJkaWRIYXZlQ3NwV2FybmluZyIsIm9uQ3NwV2FybmluZyIsIm1lc3NhZ2luZyIsInNob3dDc3BXYXJuaW5nIiwic3RyaW5ncyIsInNldHRpbmdzIiwiZGlzYWJsZVNlY3VyaXR5V2FybmluZ3MiLCJub3RpZmljYXRpb24iLCJjcmVhdGVFbGVtZW50IiwiaW5uZXJUZXh0IiwiY3NwQWxlcnRNZXNzYWdlVGV4dCIsInNldEF0dHJpYnV0ZSIsImNzcEFsZXJ0TWVzc2FnZVRpdGxlIiwiY3NwQWxlcnRNZXNzYWdlTGFiZWwiLCJvbmNsaWNrIiwiYm9keSIsImFwcGVuZENoaWxkIiwiY3NwXzEiLCJsb2FkaW5nXzEiLCJjc3BBbGVydGVyIiwic3R5bGVMb2FkaW5nTW9uaXRvciJdLCJtYXBwaW5ncyI6ImFBQ0EsSUFBQUEsS0FHQSxTQUFBQyxFQUFBQyxHQUdBLEdBQUFGLEVBQUFFLEdBQ0EsT0FBQUYsRUFBQUUsR0FBQUMsUUFHQSxJQUFBQyxFQUFBSixFQUFBRSxJQUNBRyxFQUFBSCxFQUNBSSxHQUFBLEVBQ0FILFlBVUEsT0FOQUksRUFBQUwsR0FBQU0sS0FBQUosRUFBQUQsUUFBQUMsSUFBQUQsUUFBQUYsR0FHQUcsRUFBQUUsR0FBQSxFQUdBRixFQUFBRCxRQUtBRixFQUFBUSxFQUFBRixFQUdBTixFQUFBUyxFQUFBVixFQUdBQyxFQUFBVSxFQUFBLFNBQUFSLEVBQUFTLEVBQUFDLEdBQ0FaLEVBQUFhLEVBQUFYLEVBQUFTLElBQ0FHLE9BQUFDLGVBQUFiLEVBQUFTLEdBQ0FLLGNBQUEsRUFDQUMsWUFBQSxFQUNBQyxJQUFBTixLQU1BWixFQUFBbUIsRUFBQSxTQUFBakIsR0FDQVksT0FBQUMsZUFBQWIsRUFBQSxjQUFpRGtCLE9BQUEsS0FJakRwQixFQUFBcUIsRUFBQSxTQUFBbEIsR0FDQSxJQUFBUyxFQUFBVCxLQUFBbUIsV0FDQSxXQUEyQixPQUFBbkIsRUFBQSxTQUMzQixXQUFpQyxPQUFBQSxHQUVqQyxPQURBSCxFQUFBVSxFQUFBRSxFQUFBLElBQUFBLEdBQ0FBLEdBSUFaLEVBQUFhLEVBQUEsU0FBQVUsRUFBQUMsR0FBc0QsT0FBQVYsT0FBQVcsVUFBQUMsZUFBQW5CLEtBQUFnQixFQUFBQyxJQUd0RHhCLEVBQUEyQixFQUFBLEdBSUEzQixJQUFBNEIsRUFBQSxrQ0M5REFkLE9BQUFDLGVBQUFiLEVBQUEsY0FBOENrQixPQUFBLElBQzlDLElBQUFTLE9BQUFDLEVBQ0EsU0FBQUMsRUFBQUMsR0FDQSxNQUFBQyxFQUFBQyxTQUFBQyxlQUFBLGdDQUNBLEdBQUFGLEVBQUEsQ0FDQSxNQUFBRyxFQUFBSCxFQUFBSSxhQUFBTCxHQUNBLEdBQUFJLEVBQ0EsT0FBQUUsS0FBQUMsTUFBQUgsR0FHQSxVQUFBSSxpQ0FBK0NSLEtBRS9DOUIsRUFBQTZCLFVBV0E3QixFQUFBdUMsWUFWQSxXQUNBLEdBQUFaLEVBQ0EsT0FBQUEsRUFHQSxHQURBQSxFQUFBRSxFQUFBLGlCQUVBLE9BQUFGLEVBRUEsVUFBQVcsTUFBQSwyREN6QkExQixPQUFBQyxlQUFBYixFQUFBLGNBQThDa0IsT0FBQSxJQWlDOUNsQixFQUFBd0MsMEJBL0JBQyxjQUNBQyxLQUFBQyxrQkFDQUQsS0FBQUUsaUJBQUEsRUFDQSxNQUFBQyxFQUFBQyxJQUNBLE1BQUFDLEVBQUFELEVBQUFFLE9BQUFDLFFBQUFGLE9BQ0FMLEtBQUFDLGVBQUFPLEtBQUFILElBRUFJLE9BQUFDLGlCQUFBLHdCQUNBLFVBQUFDLEtBQUFyQixTQUFBc0IsdUJBQUEsbUJBQ0FELEVBQUFKLFFBQUFGLFNBQ0FNLEVBQUFFLFFBQUFWLEtBSUFNLE9BQUFDLGlCQUFBLFlBQ0FWLEtBQUFDLGVBQUFhLFNBR0FkLEtBQUFFLGlCQUFBLEVBQ0FGLEtBQUFlLFFBQ0FmLEtBQUFlLE9BQUFDLFlBQUEseUJBQWtFZixlQUFBRCxLQUFBQyxvQkFJbEVGLFVBQUFnQixHQUNBZixLQUFBZSxTQUNBZixLQUFBRSxpQkFDQWEsRUFBQUMsWUFBQSx5QkFBeURmLGVBQUFELEtBQUFDLGlEQ3pCekQvQixPQUFBQyxlQUFBYixFQUFBLGNBQThDa0IsT0FBQSxJQVc5Q2xCLEVBQUEyRCxXQVZBLFdBQ0EsTUFBQUMsRUFBQTVCLFNBQUFDLGVBQUEsZ0NBQ0EsR0FBQTJCLEVBQUEsQ0FDQSxNQUFBMUIsRUFBQTBCLEVBQUF6QixhQUFBLGdCQUNBLEdBQUFELEVBQ0EsT0FBQUUsS0FBQUMsTUFBQUgsR0FHQSxVQUFBSSxNQUFBLHlEQ1RBMUIsT0FBQUMsZUFBQWIsRUFBQSxjQUE4Q2tCLE9BQUEsSUFDOUMsTUFBQTJDLEVBQUEvRCxFQUFBLEdBQ0FnRSxFQUFBaEUsRUFBQSxHQThDQUUsRUFBQStELGlCQXpDQXRCLGNBQ0FDLEtBQUFzQixTQUFBLEVBQ0F0QixLQUFBdUIsbUJBQUEsRUFDQWpDLFNBQUFvQixpQkFBQSwrQkFDQVYsS0FBQXdCLGlCQUVBZixPQUFBQyxpQkFBQSxVQUFBTixJQUNBQSxLQUFBWixNQUFBLHlCQUFBWSxFQUFBWixLQUFBekIsTUFDQWlDLEtBQUF3QixpQkFJQXpCLFVBQUFnQixHQUNBZixLQUFBeUIsVUFBQVYsRUFDQWYsS0FBQXVCLG1CQUNBdkIsS0FBQTBCLGlCQUdBM0IsZUFDQUMsS0FBQXVCLG1CQUFBLEVBQ0F2QixLQUFBMEIsaUJBRUEzQixpQkFDQSxNQUFBNEIsRUFBQVAsRUFBQUgsYUFDQVcsRUFBQVQsRUFBQXRCLGNBQ0EsR0FBQUcsS0FBQXNCLFNBQUFNLEVBQUFDLDBCQUFBN0IsS0FBQXlCLFVBQ0EsT0FFQXpCLEtBQUFzQixTQUFBLEVBQ0EsTUFBQVEsRUFBQXhDLFNBQUF5QyxjQUFBLEtBQ0FELEVBQUFFLFVBQUFMLEVBQUFNLG9CQUNBSCxFQUFBSSxhQUFBLHlCQUNBSixFQUFBSSxhQUFBLFFBQUFQLEVBQUFRLHNCQUNBTCxFQUFBSSxhQUFBLGlCQUNBSixFQUFBSSxhQUFBLGFBQUFQLEVBQUFTLHNCQUNBTixFQUFBTyxRQUFBLE1BQ0FyQyxLQUFBeUIsVUFBQVQsWUFBQSwrQkFBdUVYLE9BQUF1QixFQUFBdkIsV0FFdkVmLFNBQUFnRCxLQUFBQyxZQUFBVCxtQ0M3Q0E1RCxPQUFBQyxlQUFBYixFQUFBLGNBQThDa0IsT0FBQSxJQUM5QyxNQUFBZ0UsRUFBQXBGLEVBQUEsR0FDQXFGLEVBQUFyRixFQUFBLEdBQ0FxRCxPQUFBaUMsV0FBQSxJQUFBRixFQUFBbkIsV0FDQVosT0FBQWtDLG9CQUFBLElBQUFGLEVBQUEzQyIsImZpbGUiOiJwcmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDUpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxldCBjYWNoZWRTZXR0aW5ncyA9IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIGdldERhdGEoa2V5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbmZ1bmN0aW9uIGdldFNldHRpbmdzKCkge1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuICAgIGlmIChjYWNoZWRTZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U2V0dGluZ3MgPSBnZXRTZXR0aW5ncztcbiIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY2xhc3MgU3R5bGVMb2FkaW5nTW9uaXRvciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMudW5sb2FkZWRTdHlsZXMgPSBbXTtcbiAgICAgICAgdGhpcy5maW5pc2hlZExvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgY29uc3Qgb25TdHlsZUxvYWRFcnJvciA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gZXZlbnQudGFyZ2V0LmRhdGFzZXQuc291cmNlO1xuICAgICAgICAgICAgdGhpcy51bmxvYWRlZFN0eWxlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgIH07XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBsaW5rIG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2NvZGUtdXNlci1zdHlsZScpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmsuZGF0YXNldC5zb3VyY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbGluay5vbmVycm9yID0gb25TdHlsZUxvYWRFcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsICgpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy51bmxvYWRlZFN0eWxlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmZpbmlzaGVkTG9hZGluZyA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy5wb3N0ZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvc3Rlci5wb3N0TWVzc2FnZSgncHJldmlld1N0eWxlTG9hZEVycm9yJywgeyB1bmxvYWRlZFN0eWxlczogdGhpcy51bmxvYWRlZFN0eWxlcyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHNldFBvc3Rlcihwb3N0ZXIpIHtcbiAgICAgICAgdGhpcy5wb3N0ZXIgPSBwb3N0ZXI7XG4gICAgICAgIGlmICh0aGlzLmZpbmlzaGVkTG9hZGluZykge1xuICAgICAgICAgICAgcG9zdGVyLnBvc3RNZXNzYWdlKCdwcmV2aWV3U3R5bGVMb2FkRXJyb3InLCB7IHVubG9hZGVkU3R5bGVzOiB0aGlzLnVubG9hZGVkU3R5bGVzIH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0cy5TdHlsZUxvYWRpbmdNb25pdG9yID0gU3R5bGVMb2FkaW5nTW9uaXRvcjtcbiIsIlwidXNlIHN0cmljdFwiO1xuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiBnZXRTdHJpbmdzKCkge1xuICAgIGNvbnN0IHN0b3JlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3ZzY29kZS1tYXJrZG93bi1wcmV2aWV3LWRhdGEnKTtcbiAgICBpZiAoc3RvcmUpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHN0b3JlLmdldEF0dHJpYnV0ZSgnZGF0YS1zdHJpbmdzJyk7XG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHN0cmluZ3MnKTtcbn1cbmV4cG9ydHMuZ2V0U3RyaW5ncyA9IGdldFN0cmluZ3M7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3Qgc2V0dGluZ3NfMSA9IHJlcXVpcmUoXCIuL3NldHRpbmdzXCIpO1xuY29uc3Qgc3RyaW5nc18xID0gcmVxdWlyZShcIi4vc3RyaW5nc1wiKTtcbi8qKlxuICogU2hvd3MgYW4gYWxlcnQgd2hlbiB0aGVyZSBpcyBhIGNvbnRlbnQgc2VjdXJpdHkgcG9saWN5IHZpb2xhdGlvbi5cbiAqL1xuY2xhc3MgQ3NwQWxlcnRlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZGlkU2hvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRpZEhhdmVDc3BXYXJuaW5nID0gZmFsc2U7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3NlY3VyaXR5cG9saWN5dmlvbGF0aW9uJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vbkNzcFdhcm5pbmcoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQgJiYgZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhLm5hbWUgPT09ICd2c2NvZGUtZGlkLWJsb2NrLXN2ZycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ3NwV2FybmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2V0UG9zdGVyKHBvc3Rlcikge1xuICAgICAgICB0aGlzLm1lc3NhZ2luZyA9IHBvc3RlcjtcbiAgICAgICAgaWYgKHRoaXMuZGlkSGF2ZUNzcFdhcm5pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0NzcFdhcm5pbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBvbkNzcFdhcm5pbmcoKSB7XG4gICAgICAgIHRoaXMuZGlkSGF2ZUNzcFdhcm5pbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLnNob3dDc3BXYXJuaW5nKCk7XG4gICAgfVxuICAgIHNob3dDc3BXYXJuaW5nKCkge1xuICAgICAgICBjb25zdCBzdHJpbmdzID0gc3RyaW5nc18xLmdldFN0cmluZ3MoKTtcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBzZXR0aW5nc18xLmdldFNldHRpbmdzKCk7XG4gICAgICAgIGlmICh0aGlzLmRpZFNob3cgfHwgc2V0dGluZ3MuZGlzYWJsZVNlY3VyaXR5V2FybmluZ3MgfHwgIXRoaXMubWVzc2FnaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaWRTaG93ID0gdHJ1ZTtcbiAgICAgICAgY29uc3Qgbm90aWZpY2F0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICBub3RpZmljYXRpb24uaW5uZXJUZXh0ID0gc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VUZXh0O1xuICAgICAgICBub3RpZmljYXRpb24uc2V0QXR0cmlidXRlKCdpZCcsICdjb2RlLWNzcC13YXJuaW5nJyk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VUaXRsZSk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnYnV0dG9uJyk7XG4gICAgICAgIG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBzdHJpbmdzLmNzcEFsZXJ0TWVzc2FnZUxhYmVsKTtcbiAgICAgICAgbm90aWZpY2F0aW9uLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2luZy5wb3N0TWVzc2FnZSgnc2hvd1ByZXZpZXdTZWN1cml0eVNlbGVjdG9yJywgeyBzb3VyY2U6IHNldHRpbmdzLnNvdXJjZSB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChub3RpZmljYXRpb24pO1xuICAgIH1cbn1cbmV4cG9ydHMuQ3NwQWxlcnRlciA9IENzcEFsZXJ0ZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY3NwXzEgPSByZXF1aXJlKFwiLi9jc3BcIik7XG5jb25zdCBsb2FkaW5nXzEgPSByZXF1aXJlKFwiLi9sb2FkaW5nXCIpO1xud2luZG93LmNzcEFsZXJ0ZXIgPSBuZXcgY3NwXzEuQ3NwQWxlcnRlcigpO1xud2luZG93LnN0eWxlTG9hZGluZ01vbml0b3IgPSBuZXcgbG9hZGluZ18xLlN0eWxlTG9hZGluZ01vbml0b3IoKTtcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 4cd76c86007..482d0e6133d 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -314,7 +314,7 @@ "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", - "build-preview": "webpack --mode development" + "build-preview": "webpack --mode production" }, "dependencies": { "highlight.js": "9.15.8", diff --git a/extensions/markdown-language-features/preview-src/index.ts b/extensions/markdown-language-features/preview-src/index.ts index aff7254ea79..1dbde3ed4e5 100644 --- a/extensions/markdown-language-features/preview-src/index.ts +++ b/extensions/markdown-language-features/preview-src/index.ts @@ -19,7 +19,7 @@ const settings = getSettings(); const vscode = acquireVsCodeApi(); // Set VS Code state -let state = getData<{ line: number, fragment: string }>('data-state'); +let state = getData<{ line: number; fragment: string; }>('data-state'); vscode.setState(state); const messaging = createPosterForVsCode(vscode); @@ -67,7 +67,7 @@ const onUpdateView = (() => { })(); let updateImageSizes = throttle(() => { - const imageInfo: { id: string, height: number, width: number }[] = []; + const imageInfo: { id: string, height: number, width: number; }[] = []; let images = document.getElementsByTagName('img'); if (images) { let i; @@ -129,6 +129,8 @@ document.addEventListener('dblclick', event => { } }); +const passThroughLinkSchemes = ['http:', 'https:', 'mailto:', 'vscode:', 'vscode-insiders']; + document.addEventListener('click', event => { if (!event) { return; @@ -138,20 +140,25 @@ document.addEventListener('click', event => { while (node) { if (node.tagName && node.tagName === 'A' && node.href) { if (node.getAttribute('href').startsWith('#')) { - break; + return; } - if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { - const [path, fragment] = node.href - .replace(/^file:\/\//i, '') - .replace(/^vscode-resource:\/\/[^\/]+\//i, '') - .replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)) - .split('#'); - messaging.postMessage('clickLink', { path, fragment }); + + // Pass through known schemes + if (passThroughLinkSchemes.some(scheme => node.href.startsWith(scheme))) { + return; + } + + const hrefText = node.getAttribute('data-href') || node.getAttribute('href'); + + // If original link doesn't look like a url, delegate back to VS Code to resolve + if (!/^[a-z\-]+:/i.test(hrefText)) { + messaging.postMessage('openLink', { href: hrefText }); event.preventDefault(); event.stopPropagation(); - break; + return; } - break; + + return; } node = node.parentNode; } @@ -170,6 +177,3 @@ window.addEventListener('scroll', throttle(() => { } }, 50)); -function escapeRegExp(text: string) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); -} diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index b1cbe39e5af..13f6d792a2d 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -25,7 +25,7 @@ interface WebviewMessage { interface CacheImageSizesMessage extends WebviewMessage { readonly type: 'cacheImageSizes'; - readonly body: { id: string, width: number, height: number }[]; + readonly body: { id: string, width: number, height: number; }[]; } interface RevealLineMessage extends WebviewMessage { @@ -43,10 +43,9 @@ interface DidClickMessage extends WebviewMessage { } interface ClickLinkMessage extends WebviewMessage { - readonly type: 'clickLink'; + readonly type: 'openLink'; readonly body: { - readonly path: string; - readonly fragment?: string; + readonly href: string; }; } @@ -88,7 +87,7 @@ export class MarkdownPreview extends Disposable { private forceUpdate = false; private isScrolling = false; private _disposed: boolean = false; - private imageInfo: { id: string, width: number, height: number }[] = []; + private imageInfo: { id: string, width: number, height: number; }[] = []; private scrollToFragment: string | undefined; public static async revive( @@ -202,8 +201,8 @@ export class MarkdownPreview extends Disposable { this.onDidClickPreview(e.body.line); break; - case 'clickLink': - this.onDidClickPreviewLink(e.body.path, e.body.fragment); + case 'openLink': + this.onDidClickPreviewLink(e.body.href); break; case 'showPreviewSecuritySelector': @@ -536,12 +535,19 @@ export class MarkdownPreview extends Disposable { this.editor.webview.html = html; } - private async onDidClickPreviewLink(path: string, fragment: string | undefined) { - this.scrollToFragment = undefined; + private async onDidClickPreviewLink(href: string) { + let [hrefPath, fragment] = href.split('#'); + + // We perviously already resolve absolute paths. + // Now make sure we handle relative file paths + if (hrefPath[0] !== '/') { + hrefPath = path.join(path.dirname(this.resource.path), hrefPath); + } + const config = vscode.workspace.getConfiguration('markdown', this.resource); const openLinks = config.get('preview.openMarkdownLinks', 'inPreview'); if (openLinks === 'inPreview') { - const markdownLink = await resolveLinkToMarkdownFile(path); + const markdownLink = await resolveLinkToMarkdownFile(hrefPath); if (markdownLink) { if (fragment) { this.scrollToFragment = fragment; @@ -551,10 +557,10 @@ export class MarkdownPreview extends Disposable { } } - vscode.commands.executeCommand('_markdown.openDocumentLink', { path, fragment, fromResource: this.resource }); + vscode.commands.executeCommand('_markdown.openDocumentLink', { path: hrefPath, fragment, fromResource: this.resource }); } - private async onCacheImageSizes(imageInfo: { id: string, width: number, height: number }[]) { + private async onCacheImageSizes(imageInfo: { id: string, width: number, height: number; }[]) { this.imageInfo = imageInfo; } } diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index bcd7dc43ff4..a4c9ae31bec 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as crypto from 'crypto'; -import { MarkdownIt, Token } from 'markdown-it'; import * as path from 'path'; +import { MarkdownIt, Token } from 'markdown-it'; import * as vscode from 'vscode'; import { MarkdownContributionProvider as MarkdownContributionProvider } from './markdownExtensions'; import { Slugifier } from './slugify'; import { SkinnyTextDocument } from './tableOfContentsProvider'; -import { getUriForLinkWithKnownExternalScheme } from './util/links'; +import { Schemes, isOfScheme } from './util/links'; const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g; @@ -105,10 +105,10 @@ export class MarkdownEngine { this.addImageStabilizer(md); this.addFencedRenderer(md); - this.addLinkNormalizer(md); this.addLinkValidator(md); this.addNamedHeaders(md); + this.addLinkRenderer(md); return md; }); } @@ -143,6 +143,7 @@ export class MarkdownEngine { public async render(input: SkinnyTextDocument | string): Promise { const config = this.getConfig(typeof input === 'string' ? undefined : input.uri); const engine = await this.getEngine(config); + const tokens = typeof input === 'string' ? this.tokenizeString(input, engine) : this.tokenizeDocument(input, config, engine); @@ -226,36 +227,28 @@ export class MarkdownEngine { const normalizeLink = md.normalizeLink; md.normalizeLink = (link: string) => { try { - const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); - if (externalSchemeUri) { - // set true to skip encoding - return normalizeLink(externalSchemeUri.toString(true)); - } + // If original link doesn't look like a url with a scheme, assume it must be a link to a file in workspace + if (!/^[a-z\-]+:/i.test(link)) { + // Use a fake scheme for parsing + let uri = vscode.Uri.parse('markdown-link:' + link); - // Assume it must be an relative or absolute file path - // Use a fake scheme to avoid parse warnings - let uri = vscode.Uri.parse(`vscode-resource:${link}`); - - if (uri.path) { - // Assume it must be a file - const fragment = uri.fragment; + // Relative paths should be resolved correctly inside the preview but we need to + // handle absolute paths specially (for images) to resolve them relative to the workspace root if (uri.path[0] === '/') { const root = vscode.workspace.getWorkspaceFolder(this.currentDocument!); if (root) { - uri = vscode.Uri.file(path.join(root.uri.fsPath, uri.path)); + uri = uri.with({ + path: path.join(root.uri.fsPath, uri.path), + }); } - } else { - uri = vscode.Uri.file(path.join(path.dirname(this.currentDocument!.path), uri.path)); } - if (fragment) { + if (uri.fragment) { uri = uri.with({ - fragment: this.slugifier.fromHeading(fragment).value + fragment: this.slugifier.fromHeading(uri.fragment).value }); } - return normalizeLink(uri.with({ scheme: 'vscode-resource' }).toString(true)); - } else if (!uri.path && uri.fragment) { - return `#${this.slugifier.fromHeading(uri.fragment).value}`; + return normalizeLink(uri.toString(true).replace(/^markdown-link:/, '')); } } catch (e) { // noop @@ -268,7 +261,7 @@ export class MarkdownEngine { const validateLink = md.validateLink; md.validateLink = (link: string) => { // support file:// links - return validateLink(link) || link.startsWith('file:') || /^data:image\/.*?;/.test(link); + return validateLink(link) || isOfScheme(Schemes.file, link) || /^data:image\/.*?;/.test(link); }; } @@ -296,6 +289,22 @@ export class MarkdownEngine { } }; } + + private addLinkRenderer(md: any): void { + const old_render = md.renderer.rules.link_open || ((tokens: any, idx: number, options: any, _env: any, self: any) => { + return self.renderToken(tokens, idx, options); + }); + + md.renderer.rules.link_open = (tokens: any, idx: number, options: any, env: any, self: any) => { + const token = tokens[idx]; + const hrefIndex = token.attrIndex('href'); + if (hrefIndex >= 0) { + const href = token.attrs[hrefIndex][1]; + token.attrPush(['data-href', href]); + } + return old_render(tokens, idx, options, env, self); + }; + } } async function getMarkdownOptions(md: () => MarkdownIt) { diff --git a/extensions/markdown-language-features/src/util/links.ts b/extensions/markdown-language-features/src/util/links.ts index c1c2b1bdfb7..19c8627d49f 100644 --- a/extensions/markdown-language-features/src/util/links.ts +++ b/extensions/markdown-language-features/src/util/links.ts @@ -5,14 +5,30 @@ import * as vscode from 'vscode'; -const knownSchemes = ['http:', 'https:', 'file:', 'mailto:', 'data:', `${vscode.env.uriScheme}:`, 'vscode:', 'vscode-insiders:', 'vscode-resource:']; +export const Schemes = { + http: 'http:', + https: 'https:', + file: 'file:', + mailto: 'mailto:', + data: 'data:', + vscode: 'vscode:', + 'vscode-insiders': 'vscode-insiders:', + 'vscode-resource': 'vscode-resource', +} as const; -export function getUriForLinkWithKnownExternalScheme( - link: string, -): vscode.Uri | undefined { - if (knownSchemes.some(knownScheme => link.toLowerCase().startsWith(knownScheme))) { +const knownSchemes = [ + ...Object.values(Schemes), + `${vscode.env.uriScheme}:` +] as const; + +export function getUriForLinkWithKnownExternalScheme(link: string): vscode.Uri | undefined { + if (knownSchemes.some(knownScheme => isOfScheme(knownScheme, link))) { return vscode.Uri.parse(link); } return undefined; } + +export function isOfScheme(scheme: string, link: string): boolean { + return link.toLowerCase().startsWith(scheme); +} From 8e944be15cb78879f9a702c6fc933d2fa3ea9643 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 17:31:28 -0700 Subject: [PATCH 181/435] Support jsonc for code block type with highlightjs --- .../src/markdownEngine.ts | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index a4c9ae31bec..9676278f3ab 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -312,16 +312,7 @@ async function getMarkdownOptions(md: () => MarkdownIt) { return { html: true, highlight: (str: string, lang?: string) => { - // Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155 - if (lang && ['tsx', 'typescriptreact'].includes(lang.toLocaleLowerCase())) { - lang = 'jsx'; - } - if (lang && lang.toLocaleLowerCase() === 'json5') { - lang = 'json'; - } - if (lang && ['c#', 'csharp'].includes(lang.toLocaleLowerCase())) { - lang = 'cs'; - } + lang = normalizeHighlightLang(lang); if (lang && hljs.getLanguage(lang)) { try { return `
${hljs.highlight(lang, str, true).value}
`; @@ -332,3 +323,24 @@ async function getMarkdownOptions(md: () => MarkdownIt) { } }; } + +function normalizeHighlightLang(lang: string | undefined) { + switch (lang && lang.toLowerCase()) { + case 'tsx': + case 'typescriptreact': + // Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155 + return 'jsx'; + + case 'json5': + case 'jsonc': + return 'json'; + + case 'c#': + case 'csharp': + return 'cs'; + + default: + return lang; + } +} + From 45c4f228944953e310b9d8ddc2c4b2fd35e26b21 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 4 Oct 2019 17:56:41 -0700 Subject: [PATCH 182/435] Fixing more issues related to #81574 --- src/vs/workbench/browser/parts/editor/editorWidgets.ts | 2 +- src/vs/workbench/common/editor/untitledEditorInput.ts | 4 ++-- src/vs/workbench/common/editor/untitledEditorModel.ts | 4 ++-- src/vs/workbench/contrib/files/browser/views/emptyView.ts | 6 +++--- .../services/untitled/common/untitledEditorService.ts | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorWidgets.ts b/src/vs/workbench/browser/parts/editor/editorWidgets.ts index 1588d1a9341..1a311045ad9 100644 --- a/src/vs/workbench/browser/parts/editor/editorWidgets.ts +++ b/src/vs/workbench/browser/parts/editor/editorWidgets.ts @@ -31,7 +31,7 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { constructor( private editor: ICodeEditor, private label: string, - keyBindingAction: string, + keyBindingAction: string | null, @IKeybindingService keybindingService: IKeybindingService, @IThemeService private readonly themeService: IThemeService ) { diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 1ed96be6723..f9f8962e62d 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -36,8 +36,8 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport private readonly resource: URI, private readonly _hasAssociatedFilePath: boolean, private preferredMode: string, - private readonly initialValue: string, - private preferredEncoding: string, + private readonly initialValue: string | undefined, + private preferredEncoding: string | undefined, @IInstantiationService private readonly instantiationService: IInstantiationService, @ITextFileService private readonly textFileService: ITextFileService, @ILabelService private readonly labelService: ILabelService diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 3c6570c29a1..cc609638996 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -39,8 +39,8 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private readonly preferredMode: string, private readonly resource: URI, private _hasAssociatedFilePath: boolean, - private readonly initialValue: string, - private preferredEncoding: string, + private readonly initialValue: string | undefined, + private preferredEncoding: string | undefined, @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IBackupFileService private readonly backupFileService: IBackupFileService, diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index 8b54ec0abe8..c6954daaa0c 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -6,7 +6,6 @@ import * as nls from 'vs/nls'; import * as errors from 'vs/base/common/errors'; import * as DOM from 'vs/base/browser/dom'; -import { IAction } from 'vs/base/common/actions'; import { Button } from 'vs/base/browser/ui/button/button'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -84,8 +83,9 @@ export class EmptyView extends ViewletPanel { if (!this.actionRunner) { return; } - const actionClass = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? AddRootFolderAction : OpenFolderAction; - const action = this.instantiationService.createInstance(actionClass, actionClass.ID, actionClass.LABEL); + const action = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE + ? this.instantiationService.createInstance(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL) + : this.instantiationService.createInstance(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL); this.actionRunner.run(action).then(() => { action.dispose(); }, err => { diff --git a/src/vs/workbench/services/untitled/common/untitledEditorService.ts b/src/vs/workbench/services/untitled/common/untitledEditorService.ts index 8800aded809..2e9781c71c9 100644 --- a/src/vs/workbench/services/untitled/common/untitledEditorService.ts +++ b/src/vs/workbench/services/untitled/common/untitledEditorService.ts @@ -243,7 +243,7 @@ export class UntitledEditorService extends Disposable implements IUntitledEditor } } - const input = this.instantiationService.createInstance(UntitledEditorInput, untitledResource, hasAssociatedFilePath, mode, initialValue, encoding); + const input = this.instantiationService.createInstance(UntitledEditorInput, untitledResource, !!hasAssociatedFilePath, mode, initialValue, encoding); const contentListener = input.onDidModelChangeContent(() => this._onDidChangeContent.fire(untitledResource)); const dirtyListener = input.onDidChangeDirty(() => this._onDidChangeDirty.fire(untitledResource)); From c55d704a146156a1d9534d4e58d21a637308f005 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 07:58:41 +0200 Subject: [PATCH 183/435] debt - move pick & open into electron main service --- src/vs/code/electron-main/app.ts | 11 ++- src/vs/code/electron-main/main.ts | 2 +- src/vs/code/electron-main/windows.ts | 79 +------------------ .../electron-main/electronMainService.ts | 65 ++++++++++++--- .../platform/menubar/electron-main/menubar.ts | 8 +- .../platform/windows/electron-main/windows.ts | 6 -- 6 files changed, 69 insertions(+), 102 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 073b3587f81..4dce5dc8ec4 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -74,8 +74,7 @@ import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; -import { IElectronService } from 'vs/platform/electron/node/electron'; -import { ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; +import { IElectronMainService, ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService'; import { assign } from 'vs/base/common/objects'; import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; @@ -459,7 +458,7 @@ export class CodeApplication extends Disposable { services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel])); services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); - services.set(IElectronService, new SyncDescriptor(ElectronMainService)); + services.set(IElectronMainService, new SyncDescriptor(ElectronMainService)); services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService)); services.set(IMenubarService, new SyncDescriptor(MenubarMainService)); @@ -546,8 +545,8 @@ export class CodeApplication extends Disposable { const issueChannel = createChannelReceiver(issueService); electronIpcServer.registerChannel('issue', issueChannel); - const electronService = accessor.get(IElectronService); - const electronChannel = createChannelReceiver(electronService); + const electronMainService = accessor.get(IElectronMainService); + const electronChannel = createChannelReceiver(electronMainService); electronIpcServer.registerChannel('electron', electronChannel); sharedProcessClient.then(client => client.registerChannel('electron', electronChannel)); @@ -605,7 +604,7 @@ export class CodeApplication extends Disposable { }); // Create a URL handler which forwards to the last active window - const activeWindowManager = new ActiveWindowManager(electronService); + const activeWindowManager = new ActiveWindowManager(electronMainService); const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id)); const urlHandlerRouter = new URLHandlerRouter(activeWindowRouter); const urlHandlerChannel = electronIpcServer.getChannel('urlHandler', urlHandlerRouter); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 1efa3b6e3bf..65fb5ec946c 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -299,7 +299,7 @@ class CodeMain { await launchService.start(environmentService.args, process.env as platform.IProcessEnvironment); // Cleanup - await client.dispose(); + client.dispose(); // Now that we started, make sure the warning dialog is prevented if (startupWarningDialogHandle) { diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 61638921926..72ef9276caf 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -19,11 +19,10 @@ import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMai import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWaitFor, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/platform/windows/node/window'; import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; -import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; @@ -32,7 +31,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; -import { dirExists } from 'vs/base/node/pfs'; import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage'; @@ -1718,6 +1716,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { type: WindowError; }; this.telemetryService.publicLog2('windowerror', { type: error }); + // Unresponsive if (error === WindowError.UNRESPONSIVE) { if (window.isExtensionDevelopmentHost || window.isExtensionTestHost || (window.win && window.win.webContents && window.win.webContents.isDevToolsOpened())) { @@ -1790,80 +1789,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { this._onWindowClose.fire(win.id); } - async pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise { - const paths = await this.dialogMainService.pickFileFolder(options); - if (paths) { - this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData); - const urisToOpen = await Promise.all(paths.map(async path => { - const isDir = await dirExists(path); - - return isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) }; - })); - this.open({ - context: OpenContext.DIALOG, - contextWindowId: win ? win.id : undefined, - cli: this.environmentService.args, - urisToOpen, - forceNewWindow: options.forceNewWindow - }); - } - } - - async pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise { - const paths = await this.dialogMainService.pickFolder(options); - if (paths) { - this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData); - this.open({ - context: OpenContext.DIALOG, - contextWindowId: win ? win.id : undefined, - cli: this.environmentService.args, - urisToOpen: paths.map(path => ({ folderUri: URI.file(path) })), - forceNewWindow: options.forceNewWindow - }); - } - } - - async pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise { - const paths = await this.dialogMainService.pickFile(options); - if (paths) { - this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData); - this.open({ - context: OpenContext.DIALOG, - contextWindowId: win ? win.id : undefined, - cli: this.environmentService.args, - urisToOpen: paths.map(path => ({ fileUri: URI.file(path) })), - forceNewWindow: options.forceNewWindow - }); - } - } - - async pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise { - const paths = await this.dialogMainService.pickWorkspace(options); - if (paths) { - this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData); - this.open({ - context: OpenContext.DIALOG, - contextWindowId: win ? win.id : undefined, - cli: this.environmentService.args, - urisToOpen: paths.map(path => ({ workspaceUri: URI.file(path) })), - forceNewWindow: options.forceNewWindow - }); - } - - } - - private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) { - const numberOfPaths = paths ? paths.length : 0; - - // Telemetry - // __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically. - this.telemetryService.publicLog(telemetryEventName, { - ...telemetryExtraData, - outcome: numberOfPaths ? 'success' : 'canceled', - numberOfPaths - }); - } - quit(): void { // If the user selected to exit from an extension development host window, do not quit, but just diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 85bc12ccaf5..78af3d7b78b 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -16,8 +16,16 @@ import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { AddFirstParameterToFunctions } from 'vs/base/common/types'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { dirExists } from 'vs/base/node/pfs'; +import { URI } from 'vs/base/common/uri'; +import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -export class ElectronMainService implements AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { +export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { } + +export const IElectronMainService = createDecorator('electronMainService'); + +export class ElectronMainService implements IElectronMainService { _serviceBrand: undefined; @@ -25,7 +33,8 @@ export class ElectronMainService implements AddFirstParameterToFunctions { - return this.windowsMainService.pickFileFolderAndOpen(options, this.windowsMainService.getWindowById(windowId)); - } - - async pickFileAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { - return this.windowsMainService.pickFileAndOpen(options, this.windowsMainService.getWindowById(windowId)); + const paths = await this.dialogMainService.pickFileFolder(options); + if (paths) { + this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData); + this.doOpenPicked(await Promise.all(paths.map(async path => (await dirExists(path)) ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) })), options, windowId); + } } async pickFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { - return this.windowsMainService.pickFolderAndOpen(options, this.windowsMainService.getWindowById(windowId)); + const paths = await this.dialogMainService.pickFolder(options); + if (paths) { + this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData); + this.doOpenPicked(paths.map(path => ({ folderUri: URI.file(path) })), options, windowId); + } + } + + async pickFileAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { + const paths = await this.dialogMainService.pickFile(options); + if (paths) { + this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData); + this.doOpenPicked(paths.map(path => ({ fileUri: URI.file(path) })), options, windowId); + } } async pickWorkspaceAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { - return this.windowsMainService.pickWorkspaceAndOpen(options, this.windowsMainService.getWindowById(windowId)); + const paths = await this.dialogMainService.pickWorkspace(options); + if (paths) { + this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData); + this.doOpenPicked(paths.map(path => ({ workspaceUri: URI.file(path) })), options, windowId); + } + } + + private doOpenPicked(openable: IWindowOpenable[], options: INativeOpenDialogOptions, windowId: number): void { + this.windowsMainService.open({ + context: OpenContext.DIALOG, + contextWindowId: windowId, + cli: this.environmentService.args, + urisToOpen: openable, + forceNewWindow: options.forceNewWindow + }); + } + + private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) { + const numberOfPaths = paths ? paths.length : 0; + + // Telemetry + // __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically. + this.telemetryService.publicLog(telemetryEventName, { + ...telemetryExtraData, + outcome: numberOfPaths ? 'success' : 'canceled', + numberOfPaths + }); } //#endregion diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 0f00ac45280..d269dc47da4 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -22,6 +22,7 @@ import { URI } from 'vs/base/common/uri'; import { IStateService } from 'vs/platform/state/node/state'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; +import { IElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; const telemetryFrom = 'menu'; @@ -69,7 +70,8 @@ export class Menubar { @IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService, @IStateService private readonly stateService: IStateService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IElectronMainService private readonly electronMainService: IElectronMainService ) { this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0); @@ -111,8 +113,8 @@ export class Menubar { // File Menu Items this.fallbackMenuHandlers['workbench.action.files.newUntitledFile'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU); this.fallbackMenuHandlers['workbench.action.newWindow'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU); - this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.windowsMainService.pickFileFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); - this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.windowsMainService.pickWorkspaceAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); + this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.electronMainService.pickFileFolderAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); + this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.electronMainService.pickWorkspaceAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); // Recent Menu Items this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened(); diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 5dd270d8c25..4cd686508aa 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { OpenContext, IWindowConfiguration, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -97,11 +96,6 @@ export interface IWindowsMainService { openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[]; openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[]; - pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise; - pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise; - pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise; - pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise; - sendToFocused(channel: string, ...args: any[]): void; sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void; From 86a42393b0c20ee77383148174684cc5e8b6bd8e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:03:45 +0200 Subject: [PATCH 184/435] debt - handle window errors in window class --- src/vs/code/electron-main/window.ts | 96 +++++++++++++++++++ src/vs/code/electron-main/windows.ts | 81 +--------------- .../platform/windows/electron-main/windows.ts | 14 ++- 3 files changed, 108 insertions(+), 83 deletions(-) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index f136d7c7232..9746ba60a43 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -6,6 +6,7 @@ import * as path from 'vs/base/common/path'; import * as objects from 'vs/base/common/objects'; import * as nls from 'vs/nls'; +import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment } from 'electron'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; @@ -27,6 +28,9 @@ import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainServ import { endsWith } from 'vs/base/common/strings'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IFileService } from 'vs/platform/files/common/files'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { mnemonicButtonLabel } from 'vs/base/common/labels'; const RUN_TEXTMATE_IN_WORKER = false; @@ -48,6 +52,11 @@ interface ITouchBarSegment extends SegmentedControlSegment { id: string; } +const enum WindowError { + UNRESPONSIVE = 1, + CRASHED = 2 +} + export class CodeWindow extends Disposable implements ICodeWindow { private static readonly MIN_WIDTH = 200; @@ -55,6 +64,12 @@ export class CodeWindow extends Disposable implements ICodeWindow { private static readonly MAX_URL_LENGTH = 2 * 1024 * 1024; // https://cs.chromium.org/chromium/src/url/url_constants.cc?l=32 + private readonly _onClose = this._register(new Emitter()); + readonly onClose: CommonEvent = this._onClose.event; + + private readonly _onDestroy = this._register(new Emitter()); + readonly onDestroy: CommonEvent = this._onDestroy.event; + private hiddenTitleBarStyle: boolean; private showTimeoutHandle: NodeJS.Timeout; private _id: number; @@ -83,6 +98,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { @IThemeMainService private readonly themeMainService: IThemeMainService, @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, @IBackupMainService private readonly backupMainService: IBackupMainService, + @ITelemetryService private readonly telemetryService: ITelemetryService, + @IDialogMainService private readonly dialogMainService: IDialogMainService ) { super(); @@ -327,6 +344,13 @@ export class CodeWindow extends Disposable implements ICodeWindow { private registerListeners(): void { + // Crashes & Unrsponsive + this._win.webContents.on('crashed', () => this.onWindowError(WindowError.CRASHED)); + this._win.on('unresponsive', () => this.onWindowError(WindowError.UNRESPONSIVE)); + + // Window close + this._win.on('closed', () => this._onClose.fire()); + // Prevent loading of svgs this._win.webContents.session.webRequest.onBeforeRequest(null!, (details, callback) => { if (details.url.indexOf('.svg') > 0) { @@ -432,6 +456,78 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._register(this.workspacesMainService.onUntitledWorkspaceDeleted(e => this.onUntitledWorkspaceDeleted(e))); } + private onWindowError(error: WindowError): void { + this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive'); + + type WindowErrorClassification = { + type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }; + }; + type WindowErrorEvent = { + type: WindowError; + }; + this.telemetryService.publicLog2('windowerror', { type: error }); + + // Unresponsive + if (error === WindowError.UNRESPONSIVE) { + if (this.isExtensionDevelopmentHost || this.isExtensionTestHost || (this._win && this._win.webContents && this._win.webContents.isDevToolsOpened())) { + // TODO@Ben Workaround for https://github.com/Microsoft/vscode/issues/56994 + // In certain cases the window can report unresponsiveness because a breakpoint was hit + // and the process is stopped executing. The most typical cases are: + // - devtools are opened and debugging happens + // - window is an extensions development host that is being debugged + // - window is an extension test development host that is being debugged + return; + } + + // Show Dialog + this.dialogMainService.showMessageBox({ + title: product.nameLong, + type: 'warning', + buttons: [mnemonicButtonLabel(nls.localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(nls.localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(nls.localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], + message: nls.localize('appStalled', "The window is no longer responding"), + detail: nls.localize('appStalledDetail', "You can reopen or close the window or keep waiting."), + noLink: true + }, this._win).then(result => { + if (!this._win) { + return; // Return early if the window has been going down already + } + + if (result.response === 0) { + this.reload(); + } else if (result.response === 2) { + this.destroyWindow(); + } + }); + } + + // Crashed + else { + this.dialogMainService.showMessageBox({ + title: product.nameLong, + type: 'warning', + buttons: [mnemonicButtonLabel(nls.localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(nls.localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], + message: nls.localize('appCrashed', "The window has crashed"), + detail: nls.localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."), + noLink: true + }, this._win).then(result => { + if (!this._win) { + return; // Return early if the window has been going down already + } + + if (result.response === 0) { + this.reload(); + } else if (result.response === 1) { + this.destroyWindow(); + } + }); + } + } + + private destroyWindow(): void { + this._onDestroy.fire(); // 'close' event will not be fired on destroy(), so signal crash via explicit event + this._win.destroy(); // make sure to destroy the window as it has crashed + } + private onUntitledWorkspaceDeleted(workspace: IWorkspaceIdentifier): void { // Make sure to update our workspace config if we detect that it diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 72ef9276caf..4b2a3ccf233 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -22,13 +22,11 @@ import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWait import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/platform/windows/node/window'; import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources'; @@ -42,11 +40,6 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { isWindowsDriveLetter, toSlashes } from 'vs/base/common/extpath'; import { CharCode } from 'vs/base/common/charCode'; -const enum WindowError { - UNRESPONSIVE = 1, - CRASHED = 2 -} - export interface IWindowState { workspace?: IWorkspaceIdentifier; folderUri?: URI; @@ -187,7 +180,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { @IEnvironmentService private readonly environmentService: IEnvironmentService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @IBackupMainService private readonly backupMainService: IBackupMainService, - @ITelemetryService private readonly telemetryService: ITelemetryService, @IConfigurationService private readonly configurationService: IConfigurationService, @IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService, @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, @@ -1407,11 +1399,10 @@ export class WindowsManager extends Disposable implements IWindowsMainService { this._onWindowsCountChanged.fire({ oldCount: WindowsManager.WINDOWS.length - 1, newCount: WindowsManager.WINDOWS.length }); // Window Events + once(window.onClose)(() => this.onWindowClosed(window!)); + once(window.onDestroy)(() => this.onBeforeWindowClose(window!)); // try to save state before destroy because close will not fire window.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own window.win.webContents.on('devtools-reload-page', () => this.reload(window!)); - window.win.webContents.on('crashed', () => this.onWindowError(window!, WindowError.CRASHED)); - window.win.on('unresponsive', () => this.onWindowError(window!, WindowError.UNRESPONSIVE)); - window.win.on('closed', () => this.onWindowClosed(window!)); // Lifecycle (this.lifecycleMainService as LifecycleMainService).registerWindow(window); @@ -1707,74 +1698,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { return WindowsManager.WINDOWS.length; } - private onWindowError(window: ICodeWindow, error: WindowError): void { - this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive'); - type WindowErrorClassification = { - type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }; - }; - type WindowErrorEvent = { - type: WindowError; - }; - this.telemetryService.publicLog2('windowerror', { type: error }); - - // Unresponsive - if (error === WindowError.UNRESPONSIVE) { - if (window.isExtensionDevelopmentHost || window.isExtensionTestHost || (window.win && window.win.webContents && window.win.webContents.isDevToolsOpened())) { - // TODO@Ben Workaround for https://github.com/Microsoft/vscode/issues/56994 - // In certain cases the window can report unresponsiveness because a breakpoint was hit - // and the process is stopped executing. The most typical cases are: - // - devtools are opened and debugging happens - // - window is an extensions development host that is being debugged - // - window is an extension test development host that is being debugged - return; - } - - // Show Dialog - this.dialogMainService.showMessageBox({ - title: product.nameLong, - type: 'warning', - buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], - message: localize('appStalled', "The window is no longer responding"), - detail: localize('appStalledDetail', "You can reopen or close the window or keep waiting."), - noLink: true - }, window.win).then(result => { - if (!window.win) { - return; // Return early if the window has been going down already - } - - if (result.response === 0) { - window.reload(); - } else if (result.response === 2) { - this.onBeforeWindowClose(window); // 'close' event will not be fired on destroy(), so run it manually - window.win.destroy(); // make sure to destroy the window as it is unresponsive - } - }); - } - - // Crashed - else { - this.dialogMainService.showMessageBox({ - title: product.nameLong, - type: 'warning', - buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], - message: localize('appCrashed', "The window has crashed"), - detail: localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."), - noLink: true - }, window.win).then(result => { - if (!window.win) { - return; // Return early if the window has been going down already - } - - if (result.response === 0) { - window.reload(); - } else if (result.response === 1) { - this.onBeforeWindowClose(window); // 'close' event will not be fired on destroy(), so run it manually - window.win.destroy(); // make sure to destroy the window as it has crashed - } - }); - } - } - private onWindowClosed(win: ICodeWindow): void { // Tell window diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 4cd686508aa..7058b846784 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -12,6 +12,7 @@ import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { URI } from 'vs/base/common/uri'; import { Rectangle, BrowserWindow } from 'electron'; +import { IDisposable } from 'vs/base/common/lifecycle'; export interface IWindowState { width?: number; @@ -29,7 +30,11 @@ export const enum WindowMode { Fullscreen } -export interface ICodeWindow { +export interface ICodeWindow extends IDisposable { + + readonly onClose: Event; + readonly onDestroy: Event; + readonly id: number; readonly win: BrowserWindow; readonly config: IWindowConfiguration; @@ -47,6 +52,7 @@ export interface ICodeWindow { readonly isReady: boolean; ready(): Promise; + setReady(): void; addTabbedWindow(window: ICodeWindow): void; @@ -64,17 +70,17 @@ export interface ICodeWindow { toggleFullScreen(): void; isFullScreen(): boolean; isMinimized(): boolean; + hasHiddenTitleBarStyle(): boolean; + setRepresentedFilename(name: string): void; getRepresentedFilename(): string; + handleTitleDoubleClick(): void; updateTouchBar(items: ISerializableCommandAction[][]): void; - setReady(): void; serializeWindowState(): IWindowState; - - dispose(): void; } export const IWindowsMainService = createDecorator('windowsMainService'); From ffbc48855aa4032cf27b97f3363d6571e8e6203c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:09:56 +0200 Subject: [PATCH 185/435] debt - add whenClosedOrLoaded into window class --- src/vs/code/electron-main/window.ts | 27 ++++++++++++++++++- src/vs/code/electron-main/windows.ts | 27 +------------------ .../launch/electron-main/launchMainService.ts | 2 +- .../platform/windows/electron-main/windows.ts | 10 ++++--- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 9746ba60a43..b3c2af9cc48 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -70,6 +70,9 @@ export class CodeWindow extends Disposable implements ICodeWindow { private readonly _onDestroy = this._register(new Emitter()); readonly onDestroy: CommonEvent = this._onDestroy.event; + private readonly _onLoad = this._register(new Emitter()); + readonly onLoad: CommonEvent = this._onLoad.event; + private hiddenTitleBarStyle: boolean; private showTimeoutHandle: NodeJS.Timeout; private _id: number; @@ -324,6 +327,21 @@ export class CodeWindow extends Disposable implements ICodeWindow { return this._readyState === ReadyState.READY; } + get whenClosedOrLoaded(): Promise { + return new Promise(resolve => { + + function handle() { + closeListener.dispose(); + loadListener.dispose(); + + resolve(); + } + + const closeListener = this.onClose(() => handle()); + const loadListener = this.onLoad(() => handle()); + }); + } + private handleMarketplaceRequests(): void { // Resolve marketplace headers @@ -349,7 +367,11 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._win.on('unresponsive', () => this.onWindowError(WindowError.UNRESPONSIVE)); // Window close - this._win.on('closed', () => this._onClose.fire()); + this._win.on('closed', () => { + this._onClose.fire(); + + this.dispose(); + }); // Prevent loading of svgs this._win.webContents.session.webRequest.onBeforeRequest(null!, (details, callback) => { @@ -606,6 +628,9 @@ export class CodeWindow extends Disposable implements ICodeWindow { } }, 10000); } + + // Event + this._onLoad.fire(); } reload(configurationIn?: IWindowConfiguration, cli?: ParsedArgs): void { diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 4b2a3ccf233..eda372de529 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -166,9 +166,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { private readonly _onWindowClose = this._register(new Emitter()); readonly onWindowClose: CommonEvent = this._onWindowClose.event; - private readonly _onWindowLoad = this._register(new Emitter()); - readonly onWindowLoad: CommonEvent = this._onWindowLoad.event; - private readonly _onWindowsCountChanged = this._register(new Emitter()); readonly onWindowsCountChanged: CommonEvent = this._onWindowsCountChanged.event; @@ -502,7 +499,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { // process can continue. We do this by deleting the waitMarkerFilePath. const waitMarkerFileURI = openConfig.waitMarkerFileURI; if (openConfig.context === OpenContext.CLI && waitMarkerFileURI && usedWindows.length === 1 && usedWindows[0]) { - this.waitForWindowCloseOrLoad(usedWindows[0].id).then(() => fs.unlink(waitMarkerFileURI.fsPath, _error => undefined)); + usedWindows[0].whenClosedOrLoaded.then(() => fs.unlink(waitMarkerFileURI.fsPath, _error => undefined)); } return usedWindows; @@ -1456,9 +1453,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { // Load it window.load(configuration); - - // Signal event - this._onWindowLoad.fire(window.id); } private getNewWindowState(configuration: IWindowConfiguration): INewWindowState { @@ -1642,22 +1636,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow }); } - waitForWindowCloseOrLoad(windowId: number): Promise { - return new Promise(resolve => { - function handler(id: number) { - if (id === windowId) { - closeListener.dispose(); - loadListener.dispose(); - - resolve(); - } - } - - const closeListener = this.onWindowClose(id => handler(id)); - const loadListener = this.onWindowLoad(id => handler(id)); - }); - } - sendToFocused(channel: string, ...args: any[]): void { const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow(); @@ -1700,9 +1678,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService { private onWindowClosed(win: ICodeWindow): void { - // Tell window - win.dispose(); - // Remove from our list so that Electron can clean it up const index = WindowsManager.WINDOWS.indexOf(win); WindowsManager.WINDOWS.splice(index, 1); diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 9c94d83e152..026ed424e78 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -188,7 +188,7 @@ export class LaunchMainService implements ILaunchMainService { // In addition, we poll for the wait marker file to be deleted to return. if (waitMarkerFileURI && usedWindows.length === 1 && usedWindows[0]) { return Promise.race([ - this.windowsMainService.waitForWindowCloseOrLoad(usedWindows[0].id), + usedWindows[0].whenClosedOrLoaded, whenDeleted(waitMarkerFileURI.fsPath) ]).then(() => undefined, () => undefined); } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 7058b846784..8b5280ae719 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -35,6 +35,8 @@ export interface ICodeWindow extends IDisposable { readonly onClose: Event; readonly onDestroy: Event; + readonly whenClosedOrLoaded: Promise; + readonly id: number; readonly win: BrowserWindow; readonly config: IWindowConfiguration; @@ -96,12 +98,15 @@ export interface IWindowsMainService { readonly onWindowReady: Event; readonly onWindowsCountChanged: Event; - readonly onWindowClose: Event; open(openConfig: IOpenConfiguration): ICodeWindow[]; openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[]; openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[]; + closeWorkspace(win: ICodeWindow): void; + + reload(win: ICodeWindow, cli?: ParsedArgs): void; + sendToFocused(channel: string, ...args: any[]): void; sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void; @@ -111,9 +116,6 @@ export interface IWindowsMainService { getWindows(): ICodeWindow[]; getWindowCount(): number; - waitForWindowCloseOrLoad(windowId: number): Promise; - reload(win: ICodeWindow, cli?: ParsedArgs): void; - closeWorkspace(win: ICodeWindow): void; quit(): void; } From 1602957aa2f722134e37c319ef7d11d6db9f9060 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:10:21 +0200 Subject: [PATCH 186/435] debt - remove no longer needed code --- src/vs/workbench/browser/web.main.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 84c46faa362..e5e351cf7d8 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -288,14 +288,6 @@ class BrowserMain extends Disposable { let workspace: IWorkspace | undefined = undefined; if (this.configuration.workspaceProvider) { workspace = this.configuration.workspaceProvider.workspace; - } else { - // TODO@ben remove me once IWorkspaceProvider API is adopted - const legacyConfiguration = this.configuration as { workspaceUri?: URI, folderUri?: URI }; - if (legacyConfiguration.workspaceUri) { - workspace = { workspaceUri: legacyConfiguration.workspaceUri }; - } else if (legacyConfiguration.folderUri) { - workspace = { folderUri: legacyConfiguration.folderUri }; - } } // Multi-root workspace From 45856f0ebaa9301465ba86bb4010e689ea6cc2af Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:12:42 +0200 Subject: [PATCH 187/435] debt - windows => windowsMainService --- src/vs/code/electron-main/app.ts | 4 +- .../electron-main/windowsStateStorage.test.ts | 6 +-- .../electron-main/windowsMainService.ts} | 54 +++++++++---------- .../electron-main/windowsStateStorage.ts | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) rename src/vs/{code/electron-main/windows.ts => platform/windows/electron-main/windowsMainService.ts} (96%) rename src/vs/{code => platform/windows}/electron-main/windowsStateStorage.ts (97%) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 4dce5dc8ec4..9608d2fa10d 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -5,7 +5,7 @@ import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, Event as IpcMainEvent, BrowserWindow } from 'electron'; import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform'; -import { WindowsManager } from 'vs/code/electron-main/windows'; +import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { OpenContext, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { ActiveWindowManager } from 'vs/code/node/activeWindowTracker'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; @@ -449,7 +449,7 @@ export class CodeApplication extends Disposable { break; } - services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, [machineId, this.userEnv])); + services.set(IWindowsMainService, new SyncDescriptor(WindowsMainService, [machineId, this.userEnv])); services.set(IDialogMainService, new SyncDescriptor(DialogMainService)); services.set(ISharedProcessMainService, new SyncDescriptor(SharedProcessMainService, [sharedProcess])); services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService)); diff --git a/src/vs/code/test/electron-main/windowsStateStorage.test.ts b/src/vs/code/test/electron-main/windowsStateStorage.test.ts index d87d855a36b..6094456c6f5 100644 --- a/src/vs/code/test/electron-main/windowsStateStorage.test.ts +++ b/src/vs/code/test/electron-main/windowsStateStorage.test.ts @@ -6,11 +6,11 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; -import { restoreWindowsState, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage'; +import { restoreWindowsState, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage'; import { IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; -import { IWindowsState, IWindowState } from 'vs/code/electron-main/windows'; +import { IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsMainService'; function getUIState(): IWindowUIState { return { @@ -288,4 +288,4 @@ suite('Windows State Storing', () => { }); -}); \ No newline at end of file +}); diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts similarity index 96% rename from src/vs/code/electron-main/windows.ts rename to src/vs/platform/windows/electron-main/windowsMainService.ts index eda372de529..f3ce29f34a8 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -31,7 +31,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; -import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage'; +import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage'; import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -149,7 +149,7 @@ interface IWorkspacePathToOpen { label?: string; } -export class WindowsManager extends Disposable implements IWindowsMainService { +export class WindowsMainService extends Disposable implements IWindowsMainService { _serviceBrand: undefined; @@ -185,7 +185,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { ) { super(); - this.windowsState = restoreWindowsState(this.stateService.getItem(WindowsManager.windowsStateStorageKey)); + this.windowsState = restoreWindowsState(this.stateService.getItem(WindowsMainService.windowsStateStorageKey)); if (!Array.isArray(this.windowsState.openedWindows)) { this.windowsState.openedWindows = []; } @@ -299,7 +299,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { if (!currentWindowsState.lastActiveWindow) { let activeWindow = this.getLastActiveWindow(); if (!activeWindow || activeWindow.isExtensionDevelopmentHost) { - activeWindow = WindowsManager.WINDOWS.filter(window => !window.isExtensionDevelopmentHost)[0]; + activeWindow = WindowsMainService.WINDOWS.filter(window => !window.isExtensionDevelopmentHost)[0]; } if (activeWindow) { @@ -308,7 +308,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } // 2.) Find extension host window - const extensionHostWindow = WindowsManager.WINDOWS.filter(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost)[0]; + const extensionHostWindow = WindowsMainService.WINDOWS.filter(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost)[0]; if (extensionHostWindow) { currentWindowsState.lastPluginDevelopmentHostWindow = this.toWindowState(extensionHostWindow); } @@ -319,11 +319,11 @@ export class WindowsManager extends Disposable implements IWindowsMainService { // so if we ever want to persist the UI state of the last closed window (window count === 1), it has // to come from the stored lastClosedWindowState on Win/Linux at least if (this.getWindowCount() > 1) { - currentWindowsState.openedWindows = WindowsManager.WINDOWS.filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); + currentWindowsState.openedWindows = WindowsMainService.WINDOWS.filter(window => !window.isExtensionDevelopmentHost).map(window => this.toWindowState(window)); } // Persist - this.stateService.setItem(WindowsManager.windowsStateStorageKey, getWindowsStateStoreData(currentWindowsState)); + this.stateService.setItem(WindowsMainService.windowsStateStorageKey, getWindowsStateStoreData(currentWindowsState)); } // See note on #onBeforeShutdown() for details how these events are flowing @@ -546,7 +546,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { const fileToCheck = fileInputs.filesToOpenOrCreate[0] || fileInputs.filesToDiff[0]; // only look at the windows with correct authority - const windows = WindowsManager.WINDOWS.filter(window => window.remoteAuthority === fileInputs!.remoteAuthority); + const windows = WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === fileInputs!.remoteAuthority); const bestWindowOrFolder = findBestWindowOrFolderForFile({ windows, @@ -602,7 +602,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { if (allWorkspacesToOpen.length > 0) { // Check for existing instances - const windowsOnWorkspace = arrays.coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, workspaceToOpen.workspace))); + const windowsOnWorkspace = arrays.coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsMainService.WINDOWS, workspaceToOpen.workspace))); if (windowsOnWorkspace.length > 0) { const windowOnWorkspace = windowsOnWorkspace[0]; const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === windowOnWorkspace.remoteAuthority) ? fileInputs : undefined; @@ -644,7 +644,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { if (allFoldersToOpen.length > 0) { // Check for existing instances - const windowsOnFolderPath = arrays.coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, folderToOpen.folderUri))); + const windowsOnFolderPath = arrays.coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspace(WindowsMainService.WINDOWS, folderToOpen.folderUri))); if (windowsOnFolderPath.length > 0) { const windowOnFolderPath = windowsOnFolderPath[0]; const fileInputsForWindow = fileInputs && fileInputs.remoteAuthority === windowOnFolderPath.remoteAuthority ? fileInputs : undefined; @@ -1216,7 +1216,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { // Reload an existing extension development host window on the same path // We currently do not allow more than one extension development window // on the same extension path. - const existingWindow = findWindowOnExtensionDevelopmentPath(WindowsManager.WINDOWS, extensionDevelopmentPath); + const existingWindow = findWindowOnExtensionDevelopmentPath(WindowsMainService.WINDOWS, extensionDevelopmentPath); if (existingWindow) { this.reload(existingWindow, openConfig.cli); existingWindow.focus(); // make sure it gets focus and is restored @@ -1270,7 +1270,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { cliArgs = cliArgs.filter(path => { const uri = URI.file(path); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsManager.WINDOWS, uri)) { + if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, uri)) { return false; } return uri.authority === authority; @@ -1278,7 +1278,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { folderUris = folderUris.filter(uri => { const u = this.argToUri(uri); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsManager.WINDOWS, u)) { + if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, u)) { return false; } return u ? u.authority === authority : false; @@ -1286,7 +1286,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { fileUris = fileUris.filter(uri => { const u = this.argToUri(uri); - if (!!findWindowOnWorkspaceOrFolderUri(WindowsManager.WINDOWS, u)) { + if (!!findWindowOnWorkspaceOrFolderUri(WindowsMainService.WINDOWS, u)) { return false; } return u ? u.authority === authority : false; @@ -1390,10 +1390,10 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } // Add to our list of windows - WindowsManager.WINDOWS.push(window); + WindowsMainService.WINDOWS.push(window); // Indicate number change via event - this._onWindowsCountChanged.fire({ oldCount: WindowsManager.WINDOWS.length - 1, newCount: WindowsManager.WINDOWS.length }); + this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length - 1, newCount: WindowsMainService.WINDOWS.length }); // Window Events once(window.onClose)(() => this.onWindowClosed(window!)); @@ -1570,14 +1570,14 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } private ensureNoOverlap(state: ISingleWindowState): ISingleWindowState { - if (WindowsManager.WINDOWS.length === 0) { + if (WindowsMainService.WINDOWS.length === 0) { return state; } state.x = typeof state.x === 'number' ? state.x : 0; state.y = typeof state.y === 'number' ? state.y : 0; - const existingWindowBounds = WindowsManager.WINDOWS.map(win => win.getBounds()); + const existingWindowBounds = WindowsMainService.WINDOWS.map(win => win.getBounds()); while (existingWindowBounds.some(b => b.x === state.x || b.y === state.y)) { state.x += 30; state.y += 30; @@ -1616,11 +1616,11 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } getLastActiveWindow(): ICodeWindow | undefined { - return getLastActiveWindow(WindowsManager.WINDOWS); + return getLastActiveWindow(WindowsMainService.WINDOWS); } private getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined { - return getLastActiveWindow(WindowsManager.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); + return getLastActiveWindow(WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); } openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[] { @@ -1645,7 +1645,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void { - for (const window of WindowsManager.WINDOWS) { + for (const window of WindowsMainService.WINDOWS) { if (windowIdsToIgnore && windowIdsToIgnore.indexOf(window.id) >= 0) { continue; // do not send if we are instructed to ignore it } @@ -1664,26 +1664,26 @@ export class WindowsManager extends Disposable implements IWindowsMainService { } getWindowById(windowId: number): ICodeWindow | undefined { - const res = WindowsManager.WINDOWS.filter(window => window.id === windowId); + const res = WindowsMainService.WINDOWS.filter(window => window.id === windowId); return arrays.firstOrDefault(res); } getWindows(): ICodeWindow[] { - return WindowsManager.WINDOWS; + return WindowsMainService.WINDOWS; } getWindowCount(): number { - return WindowsManager.WINDOWS.length; + return WindowsMainService.WINDOWS.length; } private onWindowClosed(win: ICodeWindow): void { // Remove from our list so that Electron can clean it up - const index = WindowsManager.WINDOWS.indexOf(win); - WindowsManager.WINDOWS.splice(index, 1); + const index = WindowsMainService.WINDOWS.indexOf(win); + WindowsMainService.WINDOWS.splice(index, 1); // Emit - this._onWindowsCountChanged.fire({ oldCount: WindowsManager.WINDOWS.length + 1, newCount: WindowsManager.WINDOWS.length }); + this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length + 1, newCount: WindowsMainService.WINDOWS.length }); this._onWindowClose.fire(win.id); } diff --git a/src/vs/code/electron-main/windowsStateStorage.ts b/src/vs/platform/windows/electron-main/windowsStateStorage.ts similarity index 97% rename from src/vs/code/electron-main/windowsStateStorage.ts rename to src/vs/platform/windows/electron-main/windowsStateStorage.ts index 176f67d8749..165333950bc 100644 --- a/src/vs/code/electron-main/windowsStateStorage.ts +++ b/src/vs/platform/windows/electron-main/windowsStateStorage.ts @@ -5,7 +5,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows'; -import { IWindowState, IWindowsState } from 'vs/code/electron-main/windows'; +import { IWindowState, IWindowsState } from 'vs/platform/windows/electron-main/windowsMainService'; export type WindowsStateStorageData = object; From a3d77034dc82e77b40c96428841893a186ee3eaa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:14:07 +0200 Subject: [PATCH 188/435] debt - no need for explicit closeWorkspace() --- .../electron/electron-main/electronMainService.ts | 7 ------- src/vs/platform/electron/node/electron.ts | 1 - src/vs/platform/windows/electron-main/windows.ts | 2 -- .../platform/windows/electron-main/windowsMainService.ts | 8 -------- src/vs/workbench/browser/actions/workspaceActions.ts | 6 ++++-- .../workbench/services/host/browser/browserHostService.ts | 4 ---- src/vs/workbench/services/host/browser/host.ts | 6 ------ .../services/host/electron-browser/desktopHostService.ts | 4 ---- src/vs/workbench/test/workbenchTestServices.ts | 2 -- 9 files changed, 4 insertions(+), 36 deletions(-) diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 78af3d7b78b..3c9e82164e7 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -337,13 +337,6 @@ export class ElectronMainService implements IElectronMainService { } } - async closeWorkspace(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); - if (window) { - return this.windowsMainService.closeWorkspace(window); - } - } - async closeWindow(windowId: number): Promise { const window = this.windowsMainService.getWindowById(windowId); if (window) { diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/node/electron.ts index abb83c18f0d..ea86e1d0a26 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/node/electron.ts @@ -76,7 +76,6 @@ export interface IElectronService { // Lifecycle relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): Promise; reload(options?: { disableExtensions?: boolean }): Promise; - closeWorkspace(): Promise; closeWindow(): Promise; quit(): Promise; diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 8b5280ae719..e68365b6822 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -103,8 +103,6 @@ export interface IWindowsMainService { openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[]; openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[]; - closeWorkspace(win: ICodeWindow): void; - reload(win: ICodeWindow, cli?: ParsedArgs): void; sendToFocused(channel: string, ...args: any[]): void; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index f3ce29f34a8..36b344580b2 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -1595,14 +1595,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } } - closeWorkspace(win: ICodeWindow): void { - this.openInBrowserWindow({ - cli: this.environmentService.args, - windowToUse: win, - remoteAuthority: win.remoteAuthority - }); - } - focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { const lastActive = this.getLastActiveWindow(); if (lastActive) { diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 0b46377515b..d0305aa9dde 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -21,6 +21,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IHostService } from 'vs/workbench/services/host/browser/host'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; export class OpenFileAction extends Action { @@ -104,7 +105,8 @@ export class CloseWorkspaceAction extends Action { label: string, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @INotificationService private readonly notificationService: INotificationService, - @IHostService private readonly hostService: IHostService + @IHostService private readonly hostService: IHostService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService ) { super(id, label); } @@ -116,7 +118,7 @@ export class CloseWorkspaceAction extends Action { return Promise.resolve(undefined); } - return this.hostService.closeWorkspace(); + return this.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: this.environmentService.configuration.remoteAuthority }); } } diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index b9b4527ae6e..b81e66b0b7a 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -193,10 +193,6 @@ export class BrowserHostService extends Disposable implements IHostService { async reload(): Promise { window.location.reload(); } - - async closeWorkspace(): Promise { - return this.doOpenEmptyWindow({ forceReuseWindow: true }); - } } registerSingleton(IHostService, BrowserHostService, true); diff --git a/src/vs/workbench/services/host/browser/host.ts b/src/vs/workbench/services/host/browser/host.ts index b27f23f0e27..f97c8048de2 100644 --- a/src/vs/workbench/services/host/browser/host.ts +++ b/src/vs/workbench/services/host/browser/host.ts @@ -66,11 +66,5 @@ export interface IHostService { */ reload(): Promise; - /** - * Closes the currently opened folder/workspace and returns to an empty - * window. - */ - closeWorkspace(): Promise; - //#endregion } diff --git a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts b/src/vs/workbench/services/host/electron-browser/desktopHostService.ts index 0d6ff8a2a7a..17d415d16b7 100644 --- a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts +++ b/src/vs/workbench/services/host/electron-browser/desktopHostService.ts @@ -94,10 +94,6 @@ export class DesktopHostService extends Disposable implements IHostService { reload(): Promise { return this.electronService.reload(); } - - closeWorkspace(): Promise { - return this.electronService.closeWorkspace(); - } } registerSingleton(IHostService, DesktopHostService, true); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 0a726a52ff9..20bc88bbf4f 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1317,7 +1317,6 @@ export class TestHostService implements IHostService { async restart(): Promise { } async reload(): Promise { } - async closeWorkspace(): Promise { } async focus(): Promise { } @@ -1375,7 +1374,6 @@ export class TestElectronService implements IElectronService { async toggleWindowTabsBar(): Promise { } async relaunch(options?: { addArgs?: string[] | undefined; removeArgs?: string[] | undefined; } | undefined): Promise { } async reload(): Promise { } - async closeWorkspace(): Promise { } async closeWindow(): Promise { } async quit(): Promise { } async openDevTools(options?: Electron.OpenDevToolsOptions | undefined): Promise { } From fc7727b0d31ca9b9f1e3a6b9a501df0ac4205d1e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:17:06 +0200 Subject: [PATCH 189/435] debt - move out reload/quit to lifecycle service --- .../platform/driver/electron-main/driver.ts | 10 +- .../electron-main/electronMainService.ts | 139 ++++++++++-------- .../electron-main/lifecycleMainService.ts | 15 ++ .../platform/menubar/electron-main/menubar.ts | 6 +- .../platform/windows/electron-main/windows.ts | 4 - .../electron-main/windowsMainService.ts | 57 ++----- 6 files changed, 121 insertions(+), 110 deletions(-) diff --git a/src/vs/platform/driver/electron-main/driver.ts b/src/vs/platform/driver/electron-main/driver.ts index a0e9f373504..e0beffc55ed 100644 --- a/src/vs/platform/driver/electron-main/driver.ts +++ b/src/vs/platform/driver/electron-main/driver.ts @@ -19,6 +19,8 @@ import { KeybindingParser } from 'vs/base/common/keybindingParser'; import { timeout } from 'vs/base/common/async'; import { IDriver, IElement, IWindowDriver } from 'vs/platform/driver/common/driver'; import { NativeImage } from 'electron'; +import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { IElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; function isSilentKeyCode(keyCode: KeyCode) { return keyCode < KeyCode.KEY_0; @@ -35,7 +37,9 @@ export class Driver implements IDriver, IWindowDriverRegistry { constructor( private windowServer: IPCServer, private options: IDriverOptions, - @IWindowsMainService private readonly windowsMainService: IWindowsMainService + @IWindowsMainService private readonly windowsMainService: IWindowsMainService, + @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, + @IElectronMainService private readonly electronMainService: IElectronMainService ) { } async registerWindowDriver(windowId: number): Promise { @@ -75,11 +79,11 @@ export class Driver implements IDriver, IWindowDriverRegistry { throw new Error('Invalid window'); } this.reloadingWindowIds.add(windowId); - this.windowsMainService.reload(window); + this.lifecycleMainService.reload(window); } async exitApplication(): Promise { - return this.windowsMainService.quit(); + return this.electronMainService.quit(undefined); } async dispatchKeybinding(windowId: number, keybinding: string): Promise { diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 3c9e82164e7..bb666a1bc1b 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { MessageBoxOptions, shell, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; import { INativeOpenWindowOptions } from 'vs/platform/windows/node/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; @@ -21,7 +21,7 @@ import { URI } from 'vs/base/common/uri'; import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { } +export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number | undefined /* window ID */> { } export const IElectronMainService = createDecorator('electronMainService'); @@ -67,11 +67,11 @@ export class ElectronMainService implements IElectronMainService { })); } - async getWindowCount(windowId: number): Promise { + async getWindowCount(windowId: number | undefined): Promise { return this.windowsMainService.getWindowCount(); } - async getActiveWindowId(windowId: number): Promise { + async getActiveWindowId(windowId: number | undefined): Promise { const activeWindow = BrowserWindow.getFocusedWindow() || this.windowsMainService.getLastActiveWindow(); if (activeWindow) { return activeWindow.id; @@ -80,9 +80,9 @@ export class ElectronMainService implements IElectronMainService { return undefined; } - openWindow(windowId: number, options?: IOpenEmptyWindowOptions): Promise; - openWindow(windowId: number, toOpen: IWindowOpenable[], options?: INativeOpenWindowOptions): Promise; - openWindow(windowId: number, arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: INativeOpenWindowOptions): Promise { + openWindow(windowId: number | undefined, options?: IOpenEmptyWindowOptions): Promise; + openWindow(windowId: number | undefined, toOpen: IWindowOpenable[], options?: INativeOpenWindowOptions): Promise; + openWindow(windowId: number | undefined, arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: INativeOpenWindowOptions): Promise { if (Array.isArray(arg1)) { return this.doOpenWindow(windowId, arg1, arg2); } @@ -90,7 +90,7 @@ export class ElectronMainService implements IElectronMainService { return this.doOpenEmptyWindow(windowId, arg1); } - private async doOpenWindow(windowId: number, toOpen: IWindowOpenable[], options: INativeOpenWindowOptions = Object.create(null)): Promise { + private async doOpenWindow(windowId: number | undefined, toOpen: IWindowOpenable[], options: INativeOpenWindowOptions = Object.create(null)): Promise { if (toOpen.length > 0) { this.windowsMainService.open({ context: OpenContext.API, @@ -108,26 +108,26 @@ export class ElectronMainService implements IElectronMainService { } } - private async doOpenEmptyWindow(windowId: number, options?: IOpenEmptyWindowOptions): Promise { + private async doOpenEmptyWindow(windowId: number | undefined, options?: IOpenEmptyWindowOptions): Promise { this.windowsMainService.openEmptyWindow(OpenContext.API, options); } - async toggleFullScreen(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async toggleFullScreen(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { window.toggleFullScreen(); } } - async handleTitleDoubleClick(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async handleTitleDoubleClick(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { window.handleTitleDoubleClick(); } } - async isMaximized(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async isMaximized(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { return window.win.isMaximized(); } @@ -135,29 +135,29 @@ export class ElectronMainService implements IElectronMainService { return false; } - async maximizeWindow(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async maximizeWindow(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { window.win.maximize(); } } - async unmaximizeWindow(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async unmaximizeWindow(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { window.win.unmaximize(); } } - async minimizeWindow(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async minimizeWindow(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { window.win.minimize(); } } - async isWindowFocused(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async isWindowFocused(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { return window.win.isFocused(); } @@ -165,12 +165,12 @@ export class ElectronMainService implements IElectronMainService { return false; } - async focusWindow(windowId: number, options?: { windowId?: number; }): Promise { + async focusWindow(windowId: number | undefined, options?: { windowId?: number; }): Promise { if (options && typeof options.windowId === 'number') { windowId = options.windowId; } - const window = this.windowsMainService.getWindowById(windowId); + const window = this.windowById(windowId); if (window) { if (isMacintosh) { window.win.show(); @@ -184,20 +184,20 @@ export class ElectronMainService implements IElectronMainService { //#region Dialog - async showMessageBox(windowId: number, options: MessageBoxOptions): Promise { + async showMessageBox(windowId: number | undefined, options: MessageBoxOptions): Promise { return this.dialogMainService.showMessageBox(options, this.toBrowserWindow(windowId)); } - async showSaveDialog(windowId: number, options: SaveDialogOptions): Promise { + async showSaveDialog(windowId: number | undefined, options: SaveDialogOptions): Promise { return this.dialogMainService.showSaveDialog(options, this.toBrowserWindow(windowId)); } - async showOpenDialog(windowId: number, options: OpenDialogOptions): Promise { + async showOpenDialog(windowId: number | undefined, options: OpenDialogOptions): Promise { return this.dialogMainService.showOpenDialog(options, this.toBrowserWindow(windowId)); } - private toBrowserWindow(windowId: number): BrowserWindow | undefined { - const window = this.windowsMainService.getWindowById(windowId); + private toBrowserWindow(windowId: number | undefined): BrowserWindow | undefined { + const window = this.windowById(windowId); if (window) { return window.win; } @@ -205,7 +205,7 @@ export class ElectronMainService implements IElectronMainService { return undefined; } - async pickFileFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { + async pickFileFolderAndOpen(windowId: number | undefined, options: INativeOpenDialogOptions): Promise { const paths = await this.dialogMainService.pickFileFolder(options); if (paths) { this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData); @@ -213,7 +213,7 @@ export class ElectronMainService implements IElectronMainService { } } - async pickFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { + async pickFolderAndOpen(windowId: number | undefined, options: INativeOpenDialogOptions): Promise { const paths = await this.dialogMainService.pickFolder(options); if (paths) { this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData); @@ -221,7 +221,7 @@ export class ElectronMainService implements IElectronMainService { } } - async pickFileAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { + async pickFileAndOpen(windowId: number | undefined, options: INativeOpenDialogOptions): Promise { const paths = await this.dialogMainService.pickFile(options); if (paths) { this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData); @@ -229,7 +229,7 @@ export class ElectronMainService implements IElectronMainService { } } - async pickWorkspaceAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise { + async pickWorkspaceAndOpen(windowId: number | undefined, options: INativeOpenDialogOptions): Promise { const paths = await this.dialogMainService.pickWorkspace(options); if (paths) { this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData); @@ -237,7 +237,7 @@ export class ElectronMainService implements IElectronMainService { } } - private doOpenPicked(openable: IWindowOpenable[], options: INativeOpenDialogOptions, windowId: number): void { + private doOpenPicked(openable: IWindowOpenable[], options: INativeOpenDialogOptions, windowId: number | undefined): void { this.windowsMainService.open({ context: OpenContext.DIALOG, contextWindowId: windowId, @@ -263,32 +263,32 @@ export class ElectronMainService implements IElectronMainService { //#region OS - async showItemInFolder(windowId: number, path: string): Promise { + async showItemInFolder(windowId: number | undefined, path: string): Promise { shell.showItemInFolder(path); } - async setRepresentedFilename(windowId: number, path: string): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async setRepresentedFilename(windowId: number | undefined, path: string): Promise { + const window = this.windowById(windowId); if (window) { window.setRepresentedFilename(path); } } - async setDocumentEdited(windowId: number, edited: boolean): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async setDocumentEdited(windowId: number | undefined, edited: boolean): Promise { + const window = this.windowById(windowId); if (window) { window.win.setDocumentEdited(edited); } } - async openExternal(windowId: number, url: string): Promise { + async openExternal(windowId: number | undefined, url: string): Promise { shell.openExternal(url); return true; } - async updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async updateTouchBar(windowId: number | undefined, items: ISerializableCommandAction[][]): Promise { + const window = this.windowById(windowId); if (window) { window.updateTouchBar(items); } @@ -326,35 +326,48 @@ export class ElectronMainService implements IElectronMainService { //#region Lifecycle - async relaunch(windowId: number, options?: { addArgs?: string[], removeArgs?: string[] }): Promise { + async relaunch(windowId: number | undefined, options?: { addArgs?: string[], removeArgs?: string[] }): Promise { return this.lifecycleMainService.relaunch(options); } - async reload(windowId: number, options?: { disableExtensions?: boolean }): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async reload(windowId: number | undefined, options?: { disableExtensions?: boolean }): Promise { + const window = this.windowById(windowId); if (window) { - return this.windowsMainService.reload(window, options && options.disableExtensions ? { _: [], 'disable-extensions': true } : undefined); + return this.lifecycleMainService.reload(window, options && options.disableExtensions ? { _: [], 'disable-extensions': true } : undefined); } } - async closeWindow(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async closeWindow(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { return window.win.close(); } } - async quit(windowId: number): Promise { - return this.windowsMainService.quit(); + async quit(windowId: number | undefined): Promise { + + // If the user selected to exit from an extension development host window, do not quit, but just + // close the window unless this is the last window that is opened. + const window = this.windowsMainService.getLastActiveWindow(); + if (window && window.isExtensionDevelopmentHost && this.windowsMainService.getWindowCount() > 1) { + window.win.close(); + } + + // Otherwise: normal quit + else { + setTimeout(() => { + this.lifecycleMainService.quit(); + }, 10 /* delay to unwind callback stack (IPC) */); + } } //#endregion //#region Connectivity - async resolveProxy(windowId: number, url: string): Promise { + async resolveProxy(windowId: number | undefined, url: string): Promise { return new Promise(resolve => { - const window = this.windowsMainService.getWindowById(windowId); + const window = this.windowById(windowId); if (window && window.win && window.win.webContents && window.win.webContents.session) { window.win.webContents.session.resolveProxy(url, proxy => resolve(proxy)); } else { @@ -367,15 +380,15 @@ export class ElectronMainService implements IElectronMainService { //#region Development - async openDevTools(windowId: number, options?: OpenDevToolsOptions): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async openDevTools(windowId: number | undefined, options?: OpenDevToolsOptions): Promise { + const window = this.windowById(windowId); if (window) { window.win.webContents.openDevTools(options); } } - async toggleDevTools(windowId: number): Promise { - const window = this.windowsMainService.getWindowById(windowId); + async toggleDevTools(windowId: number | undefined): Promise { + const window = this.windowById(windowId); if (window) { const contents = window.win.webContents; if (isMacintosh && window.hasHiddenTitleBarStyle() && !window.isFullScreen() && !contents.isDevToolsOpened()) { @@ -386,7 +399,7 @@ export class ElectronMainService implements IElectronMainService { } } - async startCrashReporter(windowId: number, options: CrashReporterStartOptions): Promise { + async startCrashReporter(windowId: number | undefined, options: CrashReporterStartOptions): Promise { crashReporter.start(options); } @@ -396,7 +409,7 @@ export class ElectronMainService implements IElectronMainService { // TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060) - async openExtensionDevelopmentHostWindow(windowId: number, args: ParsedArgs, env: IProcessEnvironment): Promise { + async openExtensionDevelopmentHostWindow(windowId: number | undefined, args: ParsedArgs, env: IProcessEnvironment): Promise { const extDevPaths = args.extensionDevelopmentPath; if (extDevPaths) { this.windowsMainService.openExtensionDevelopmentHostWindow(extDevPaths, { @@ -408,4 +421,12 @@ export class ElectronMainService implements IElectronMainService { } //#endregion + + private windowById(windowId: number | undefined): ICodeWindow | undefined { + if (typeof windowId !== 'number') { + return undefined; + } + + return this.windowsMainService.getWindowById(windowId); + } } diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index 17253677571..d907bf1e03f 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -13,6 +13,7 @@ import { handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { Disposable } from 'vs/base/common/lifecycle'; import { Barrier } from 'vs/base/common/async'; +import { ParsedArgs } from 'vs/platform/environment/common/environment'; export const ILifecycleMainService = createDecorator('lifecycleMainService'); @@ -82,6 +83,11 @@ export interface ILifecycleMainService { */ readonly onBeforeWindowUnload: Event; + /** + * Reload a window. All lifecycle event handlers are triggered. + */ + reload(window: ICodeWindow, cli?: ParsedArgs): Promise; + /** * Unload a window for the provided reason. All lifecycle event handlers are triggered. */ @@ -360,6 +366,15 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe }); } + async reload(window: ICodeWindow, cli?: ParsedArgs): Promise { + + // Only reload when the window has not vetoed this + const veto = await this.unload(window, UnloadReason.RELOAD); + if (!veto) { + window.reload(undefined, cli); + } + } + async unload(window: ICodeWindow, reason: UnloadReason): Promise { // Always allow to unload a window that is not yet ready diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index d269dc47da4..991f2cc4b99 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -113,8 +113,8 @@ export class Menubar { // File Menu Items this.fallbackMenuHandlers['workbench.action.files.newUntitledFile'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU); this.fallbackMenuHandlers['workbench.action.newWindow'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU); - this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.electronMainService.pickFileFolderAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); - this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.electronMainService.pickWorkspaceAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); + this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.electronMainService.pickFileFolderAndOpen(undefined, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); + this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.electronMainService.pickWorkspaceAndOpen(undefined, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }); // Recent Menu Items this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened(); @@ -370,7 +370,7 @@ export class Menubar { !!BrowserWindow.getFocusedWindow() || // allow to quit when window has focus (fix for https://github.com/Microsoft/vscode/issues/39191) this.windowsMainService.getLastActiveWindow()!.isMinimized() // allow to quit when window has no focus but is minimized (https://github.com/Microsoft/vscode/issues/63000) ) { - this.windowsMainService.quit(); + this.electronMainService.quit(undefined); } } })); diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index e68365b6822..86d26e848ec 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -103,8 +103,6 @@ export interface IWindowsMainService { openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[]; openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[]; - reload(win: ICodeWindow, cli?: ParsedArgs): void; - sendToFocused(channel: string, ...args: any[]): void; sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void; @@ -113,8 +111,6 @@ export interface IWindowsMainService { getWindowById(windowId: number): ICodeWindow | undefined; getWindows(): ICodeWindow[]; getWindowCount(): number; - - quit(): void; } export interface IOpenConfiguration { diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 36b344580b2..470f036424c 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -369,6 +369,19 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic }; } + openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[] { + let cli = this.environmentService.args; + const remote = options && options.remoteAuthority; + if (cli && (cli.remote !== remote)) { + cli = { ...cli, remote }; + } + + const forceReuseWindow = options && options.forceReuseWindow; + const forceNewWindow = !forceReuseWindow; + + return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow }); + } + open(openConfig: IOpenConfiguration): ICodeWindow[] { this.logService.trace('windowsManager#open'); openConfig = this.validateOpenConfig(openConfig); @@ -1218,7 +1231,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // on the same extension path. const existingWindow = findWindowOnExtensionDevelopmentPath(WindowsMainService.WINDOWS, extensionDevelopmentPath); if (existingWindow) { - this.reload(existingWindow, openConfig.cli); + this.lifecycleMainService.reload(existingWindow, openConfig.cli); existingWindow.focus(); // make sure it gets focus and is restored return [existingWindow]; @@ -1399,7 +1412,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic once(window.onClose)(() => this.onWindowClosed(window!)); once(window.onDestroy)(() => this.onBeforeWindowClose(window!)); // try to save state before destroy because close will not fire window.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own - window.win.webContents.on('devtools-reload-page', () => this.reload(window!)); + window.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(window!)); // Lifecycle (this.lifecycleMainService as LifecycleMainService).registerWindow(window); @@ -1586,15 +1599,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return state; } - async reload(win: ICodeWindow, cli?: ParsedArgs): Promise { - - // Only reload when the window has not vetoed this - const veto = await this.lifecycleMainService.unload(win, UnloadReason.RELOAD); - if (!veto) { - win.reload(undefined, cli); - } - } - focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { const lastActive = this.getLastActiveWindow(); if (lastActive) { @@ -1615,19 +1619,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return getLastActiveWindow(WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); } - openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[] { - let cli = this.environmentService.args; - const remote = options && options.remoteAuthority; - if (cli && (cli.remote !== remote)) { - cli = { ...cli, remote }; - } - - const forceReuseWindow = options && options.forceReuseWindow; - const forceNewWindow = !forceReuseWindow; - - return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow }); - } - sendToFocused(channel: string, ...args: any[]): void { const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow(); @@ -1657,6 +1648,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic getWindowById(windowId: number): ICodeWindow | undefined { const res = WindowsMainService.WINDOWS.filter(window => window.id === windowId); + return arrays.firstOrDefault(res); } @@ -1678,21 +1670,4 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length + 1, newCount: WindowsMainService.WINDOWS.length }); this._onWindowClose.fire(win.id); } - - quit(): void { - - // If the user selected to exit from an extension development host window, do not quit, but just - // close the window unless this is the last window that is opened. - const window = this.getFocusedWindow(); - if (window && window.isExtensionDevelopmentHost && this.getWindowCount() > 1) { - window.win.close(); - } - - // Otherwise: normal quit - else { - setTimeout(() => { - this.lifecycleMainService.quit(); - }, 10 /* delay to unwind callback stack (IPC) */); - } - } } From ae891b59bca5181cad8d1b9ff4b24d30597bdd24 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:18:39 +0200 Subject: [PATCH 190/435] web - do not reload if workspace is equal --- src/vs/code/browser/workbench/workbench.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 32b5f1a0903..037e85ba25f 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -10,6 +10,7 @@ import { streamToBuffer } from 'vs/base/common/buffer'; import { Disposable } from 'vs/base/common/lifecycle'; import { request } from 'vs/base/parts/request/browser/request'; import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/windows'; +import { isEqual } from 'vs/base/common/resources'; interface ICredential { service: string; @@ -203,9 +204,12 @@ class WorkspaceProvider implements IWorkspaceProvider { constructor(public readonly workspace: IWorkspace) { } async open(workspace: IWorkspace, options?: { reuse?: boolean }): Promise { - let targetHref: string | undefined = undefined; + if (options && options.reuse && this.isSame(this.workspace, workspace)) { + return; // return early if workspace is not changing and we are reusing window + } // Empty + let targetHref: string | undefined = undefined; if (!workspace) { targetHref = `${document.location.origin}${document.location.pathname}?ew=true`; } @@ -228,6 +232,22 @@ class WorkspaceProvider implements IWorkspaceProvider { } } } + + private isSame(workspaceA: IWorkspace, workspaceB: IWorkspace): boolean { + if (!workspaceA || !workspaceB) { + return workspaceA === workspaceB; // both empty + } + + if (isFolderToOpen(workspaceA) && isFolderToOpen(workspaceB)) { + return isEqual(workspaceA.folderUri, workspaceB.folderUri); // same workspace + } + + if (isWorkspaceToOpen(workspaceA) && isWorkspaceToOpen(workspaceB)) { + return isEqual(workspaceA.workspaceUri, workspaceB.workspaceUri); // same workspace + } + + return false; + } } const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(document.getElementById('vscode-workbench-web-configuration')!.getAttribute('data-settings')!); From 875fc151e27264c801e3a7116280656b942f1cbb Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 08:18:47 +0200 Subject: [PATCH 191/435] web - store font info properly --- src/vs/workbench/browser/workbench.ts | 40 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 917a1ec5d0f..cea697d588d 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -19,7 +19,7 @@ import { IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/ import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; import { Position, Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IStorageService, WillSaveStateReason, StorageScope, IWillSaveStateEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, WillSaveStateReason, StorageScope } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -227,6 +227,20 @@ export class Workbench extends Layout { configurationService: IConfigurationService ): void { + // Configuration changes + this._register(configurationService.onDidChangeConfiguration(() => this.setFontAliasing(configurationService))); + + // Font Info + if (isNative) { + this._register(storageService.onWillSaveState(e => { + if (e.reason === WillSaveStateReason.SHUTDOWN) { + this.storeFontInfo(storageService); + } + })); + } else { + this._register(lifecycleService.onWillShutdown(() => this.storeFontInfo(storageService))); + } + // Lifecycle this._register(lifecycleService.onBeforeShutdown(event => this._onBeforeShutdown.fire(event))); this._register(lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event))); @@ -234,12 +248,6 @@ export class Workbench extends Layout { this._onShutdown.fire(); this.dispose(); })); - - // Configuration changes - this._register(configurationService.onDidChangeConfiguration(() => this.setFontAliasing(configurationService))); - - // Storage - this._register(storageService.onWillSaveState(e => this.storeFontInfo(e, storageService))); } private fontAliasing: 'default' | 'antialiased' | 'none' | 'auto' | undefined; @@ -279,13 +287,19 @@ export class Workbench extends Layout { readFontInfo(BareFontInfo.createFromRawSettings(configurationService.getValue('editor'), getZoomLevel())); } - private storeFontInfo(e: IWillSaveStateEvent, storageService: IStorageService): void { - if (e.reason === WillSaveStateReason.SHUTDOWN) { - const serializedFontInfo = serializeFontInfo(); - if (serializedFontInfo) { - const serializedFontInfoRaw = JSON.stringify(serializedFontInfo); + private storeFontInfo(storageService: IStorageService): void { + const serializedFontInfo = serializeFontInfo(); + if (serializedFontInfo) { + const serializedFontInfoRaw = JSON.stringify(serializedFontInfo); - isNative ? storageService.store('editorFontInfo', serializedFontInfoRaw, StorageScope.GLOBAL) : window.localStorage.setItem('editorFontInfo', serializedFontInfoRaw); + // Font info is very specific to the machine the workbench runs + // on. As such, in the web, we prefer to store this info in + // local storage and not global storage because it would not make + // much sense to synchronize to other machines. + if (isNative) { + storageService.store('editorFontInfo', serializedFontInfoRaw, StorageScope.GLOBAL); + } else { + window.localStorage.setItem('editorFontInfo', serializedFontInfoRaw); } } } From c617db19b08bfdae8e2c540470bf82dd405c3895 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 5 Oct 2019 16:11:41 +0200 Subject: [PATCH 192/435] debt - some strict function types (#81574) --- src/vs/code/electron-main/main.ts | 33 ++++++++++--------- src/vs/workbench/browser/labels.ts | 4 +-- .../parts/activitybar/activitybarPart.ts | 2 +- .../browser/parts/editor/editorGroupView.ts | 4 +-- .../browser/parts/editor/editorPicker.ts | 4 +-- .../common/editor/binaryEditorModel.ts | 6 ++-- .../common/editor/resourceEditorInput.ts | 5 +-- .../common/editor/untitledEditorInput.ts | 2 +- .../common/editor/untitledEditorModel.ts | 2 +- .../contrib/files/browser/saveErrorHandler.ts | 2 +- .../contrib/search/browser/openFileHandler.ts | 4 +-- 11 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 65fb5ec946c..9a4f97020eb 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -6,7 +6,7 @@ import 'vs/platform/update/common/update.config.contribution'; import { app, dialog } from 'electron'; import { assign } from 'vs/base/common/objects'; -import * as platform from 'vs/base/common/platform'; +import { isWindows, IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import product from 'vs/platform/product/common/product'; import { parseMainProcessArgv } from 'vs/platform/environment/node/argvHelper'; import { addArg, createWaitMarkerFile } from 'vs/platform/environment/node/argv'; @@ -132,7 +132,7 @@ class CodeMain { } } - private createServices(args: ParsedArgs, bufferLogService: BufferLogService): [IInstantiationService, typeof process.env] { + private createServices(args: ParsedArgs, bufferLogService: BufferLogService): [IInstantiationService, IProcessEnvironment] { const services = new ServiceCollection(); const environmentService = new EnvironmentService(args, process.execPath); @@ -174,16 +174,17 @@ class CodeMain { return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]); } - private patchEnvironment(environmentService: IEnvironmentService): typeof process.env { - const instanceEnvironment: typeof process.env = { - VSCODE_IPC_HOOK: environmentService.mainIPCHandle, - VSCODE_NLS_CONFIG: process.env['VSCODE_NLS_CONFIG'], - VSCODE_LOGS: process.env['VSCODE_LOGS'] + private patchEnvironment(environmentService: IEnvironmentService): IProcessEnvironment { + const instanceEnvironment: IProcessEnvironment = { + VSCODE_IPC_HOOK: environmentService.mainIPCHandle }; - if (process.env['VSCODE_PORTABLE']) { - instanceEnvironment['VSCODE_PORTABLE'] = process.env['VSCODE_PORTABLE']; - } + ['VSCODE_NLS_CONFIG', 'VSCODE_LOGS', 'VSCODE_PORTABLE'].forEach(key => { + const value = process.env[key]; + if (typeof value === 'string') { + instanceEnvironment[key] = value; + } + }); assign(process.env, instanceEnvironment); @@ -213,7 +214,7 @@ class CodeMain { } // Since we are the second instance, we do not want to show the dock - if (platform.isMacintosh) { + if (isMacintosh) { app.dock.hide(); } @@ -224,7 +225,7 @@ class CodeMain { } catch (error) { // Handle unexpected connection errors by showing a dialog to the user - if (!retry || platform.isWindows || error.code !== 'ECONNREFUSED') { + if (!retry || isWindows || error.code !== 'ECONNREFUSED') { if (error.code === 'EPERM') { this.showStartupWarningDialog( localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort), @@ -290,13 +291,13 @@ class CodeMain { } // Windows: allow to set foreground - if (platform.isWindows) { + if (isWindows) { await this.windowsAllowSetForegroundWindow(launchService, logService); } // Send environment over... logService.trace('Sending env to running instance...'); - await launchService.start(environmentService.args, process.env as platform.IProcessEnvironment); + await launchService.start(environmentService.args, process.env as IProcessEnvironment); // Cleanup client.dispose(); @@ -317,7 +318,7 @@ class CodeMain { } // dock might be hidden at this case due to a retry - if (platform.isMacintosh) { + if (isMacintosh) { app.dock.show(); } @@ -359,7 +360,7 @@ class CodeMain { } private async windowsAllowSetForegroundWindow(launchService: ILaunchMainService, logService: ILogService): Promise { - if (platform.isWindows) { + if (isWindows) { const processId = await launchService.getMainProcessId(); logService.trace('Sending some foreground love to the running instance:', processId); diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 2b5d9be8790..d9e9d143bed 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -211,7 +211,7 @@ export class ResourceLabel extends ResourceLabels { constructor( container: HTMLElement, - options: IIconLabelCreationOptions, + options: IIconLabelCreationOptions | undefined, @IInstantiationService instantiationService: IInstantiationService, @IExtensionService extensionService: IExtensionService, @IConfigurationService configurationService: IConfigurationService, @@ -252,7 +252,7 @@ class ResourceLabelWidget extends IconLabel { constructor( container: HTMLElement, - options: IIconLabelCreationOptions, + options: IIconLabelCreationOptions | undefined, @IModeService private readonly modeService: IModeService, @IModelService private readonly modelService: IModelService, @IDecorationsService private readonly decorationsService: IDecorationsService, diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e98dc753597..14848f29ec1 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -280,7 +280,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private createGlobalActivityActionBar(container: HTMLElement): void { this.globalActivityActionBar = this._register(new ActionBar(container, { - actionViewItemProvider: a => this.instantiationService.createInstance(GlobalActivityActionViewItem, a, (theme: ITheme) => this.getActivitybarItemColors(theme)), + actionViewItemProvider: action => this.instantiationService.createInstance(GlobalActivityActionViewItem, action, (theme: ITheme) => this.getActivitybarItemColors(theme)), orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('manage', "Manage"), animated: false diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 72708e0a4b9..8f4e19ed022 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -119,7 +119,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { constructor( private accessor: IEditorGroupsAccessor, - from: IEditorGroupView | ISerializedEditorGroup, + from: IEditorGroupView | ISerializedEditorGroup | null, private _index: number, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -420,7 +420,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } } - private async restoreEditors(from: IEditorGroupView | ISerializedEditorGroup): Promise { + private async restoreEditors(from: IEditorGroupView | ISerializedEditorGroup | null): Promise { if (this._group.count === 0) { return; // nothing to show } diff --git a/src/vs/workbench/browser/parts/editor/editorPicker.ts b/src/vs/workbench/browser/parts/editor/editorPicker.ts index a3d495473f5..1c8e7996d06 100644 --- a/src/vs/workbench/browser/parts/editor/editorPicker.ts +++ b/src/vs/workbench/browser/parts/editor/editorPicker.ts @@ -15,7 +15,7 @@ import { QuickOpenHandler } from 'vs/workbench/browser/quickopen'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupsService, IEditorGroup, EditorsOrder, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EditorInput, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; +import { toResource, SideBySideEditor, IEditorInput } from 'vs/workbench/common/editor'; import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; import { CancellationToken } from 'vs/base/common/cancellation'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -23,7 +23,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; export class EditorPickerEntry extends QuickOpenEntryGroup { constructor( - private editor: EditorInput, + private editor: IEditorInput, private _group: IEditorGroup, @IModeService private readonly modeService: IModeService, @IModelService private readonly modelService: IModelService diff --git a/src/vs/workbench/common/editor/binaryEditorModel.ts b/src/vs/workbench/common/editor/binaryEditorModel.ts index 48c1cf5582c..dc631e33a88 100644 --- a/src/vs/workbench/common/editor/binaryEditorModel.ts +++ b/src/vs/workbench/common/editor/binaryEditorModel.ts @@ -7,7 +7,7 @@ import { EditorModel } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; -import { DataUri } from 'vs/base/common/resources'; +import { DataUri, basename } from 'vs/base/common/resources'; /** * An editor model that just represents a resource that can be loaded. @@ -19,7 +19,7 @@ export class BinaryEditorModel extends EditorModel { constructor( private readonly resource: URI, - private readonly name: string, + private readonly name: string | undefined, @IFileService private readonly fileService: IFileService ) { super(); @@ -41,7 +41,7 @@ export class BinaryEditorModel extends EditorModel { * The name of the binary resource. */ getName(): string { - return this.name; + return this.name || basename(this.resource); } /** diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index 1d7712d1c4e..ee9605889c4 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { IReference } from 'vs/base/common/lifecycle'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; +import { basename } from 'vs/base/common/resources'; /** * A read-only text editor input whos contents are made of the provided resource that points to an existing @@ -21,7 +22,7 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport { private modelReference: Promise> | null = null; constructor( - private name: string, + private name: string | undefined, private description: string | undefined, private readonly resource: URI, private preferredMode: string | undefined, @@ -43,7 +44,7 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport { } getName(): string { - return this.name; + return this.name || basename(this.resource); } setName(name: string): void { diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index f9f8962e62d..a446559f1ed 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -35,7 +35,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport constructor( private readonly resource: URI, private readonly _hasAssociatedFilePath: boolean, - private preferredMode: string, + private preferredMode: string | undefined, private readonly initialValue: string | undefined, private preferredEncoding: string | undefined, @IInstantiationService private readonly instantiationService: IInstantiationService, diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index cc609638996..152eea5f386 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -36,7 +36,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private configuredEncoding?: string; constructor( - private readonly preferredMode: string, + private readonly preferredMode: string | undefined, private readonly resource: URI, private _hasAssociatedFilePath: boolean, private readonly initialValue: string | undefined, diff --git a/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts b/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts index 608638b5178..fb12ef07f89 100644 --- a/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts +++ b/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts @@ -141,7 +141,7 @@ export class SaveErrorHandler extends Disposable implements ISaveErrorHandler, I // Save Elevated if (canHandlePermissionOrReadonlyErrors && (isPermissionDenied || triedToMakeWriteable)) { - primaryActions.push(this.instantiationService.createInstance(SaveElevatedAction, model, triedToMakeWriteable)); + primaryActions.push(this.instantiationService.createInstance(SaveElevatedAction, model, !!triedToMakeWriteable)); } // Overwrite diff --git a/src/vs/workbench/contrib/search/browser/openFileHandler.ts b/src/vs/workbench/contrib/search/browser/openFileHandler.ts index 0374b69749f..c2ecf876664 100644 --- a/src/vs/workbench/contrib/search/browser/openFileHandler.ts +++ b/src/vs/workbench/contrib/search/browser/openFileHandler.ts @@ -50,7 +50,7 @@ export class FileEntry extends EditorQuickOpenEntry { private resource: URI, private name: string, private description: string, - private icon: string, + private icon: string | undefined, @IEditorService editorService: IEditorService, @IModeService private readonly modeService: IModeService, @IModelService private readonly modelService: IModelService, @@ -78,7 +78,7 @@ export class FileEntry extends EditorQuickOpenEntry { return this.description; } - getIcon(): string { + getIcon(): string | undefined { return this.icon; } From c71cbdaa1b946dd1e3f58afcd4c220a7f4da14bd Mon Sep 17 00:00:00 2001 From: Nikolay Kondratyev Date: Sun, 6 Oct 2019 22:34:24 +0300 Subject: [PATCH 193/435] Render Octicons in CodeLens --- src/vs/editor/contrib/codelens/codelensWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/codelens/codelensWidget.ts b/src/vs/editor/contrib/codelens/codelensWidget.ts index 42cf0deb06e..5465476d6ed 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.ts +++ b/src/vs/editor/contrib/codelens/codelensWidget.ts @@ -6,7 +6,7 @@ import 'vs/css!./codelensWidget'; import * as dom from 'vs/base/browser/dom'; import { coalesce, isFalsyOrEmpty } from 'vs/base/common/arrays'; -import { escape } from 'vs/base/common/strings'; +import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; import { IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model'; @@ -104,7 +104,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { for (let i = 0; i < symbols.length; i++) { const command = symbols[i].command; if (command) { - const title = escape(command.title); + const title = renderOcticons(command.title); let part: string; if (command.id) { part = `${title}`; From e257fad18a6b85bc6fb2e7e42de7510bfb6d7464 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Oct 2019 12:42:04 +0200 Subject: [PATCH 194/435] deco - some debt, add logging --- .../decorations/browser/decorationsService.ts | 46 ++++++++----------- .../test/browser/decorationsService.test.ts | 7 +-- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index cde13b00f2c..6e7d60942b4 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { IDecorationsService, IDecoration, IResourceDecorationChangeEvent, IDecorationsProvider, IDecorationData } from './decorations'; import { TernarySearchTree } from 'vs/base/common/map'; -import { Disposable, IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { isThenable } from 'vs/base/common/async'; import { LinkedList } from 'vs/base/common/linkedList'; import { createStyleSheet, createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom'; @@ -19,6 +19,7 @@ import { localize } from 'vs/nls'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ILogService } from 'vs/platform/log/common/log'; class DecorationRule { @@ -96,25 +97,21 @@ class DecorationRule { } } -class DecorationStyles extends Disposable { +class DecorationStyles { private readonly _styleElement = createStyleSheet(); private readonly _decorationRules = new Map(); + private readonly _dispoables = new DisposableStore(); constructor( private _themeService: IThemeService, ) { - super(); - this._register(this._themeService.onThemeChange(this._onThemeChange, this)); + this._themeService.onThemeChange(this._onThemeChange, this, this._dispoables); } dispose(): void { - super.dispose(); - - const parent = this._styleElement.parentElement; - if (parent) { - parent.removeChild(this._styleElement); - } + this._dispoables.dispose(); + this._styleElement.remove(); } asDecoration(data: IDecorationData[], onlyChildren: boolean): IDecoration { @@ -224,11 +221,11 @@ class DecorationProviderWrapper { private readonly _dispoable: IDisposable; constructor( - private readonly _provider: IDecorationsProvider, + readonly provider: IDecorationsProvider, private readonly _uriEmitter: Emitter, private readonly _flushEmitter: Emitter ) { - this._dispoable = this._provider.onDidChange(uris => { + this._dispoable = this.provider.onDidChange(uris => { if (!uris) { // flush event -> drop all data, can affect everything this.data.clear(); @@ -292,7 +289,7 @@ class DecorationProviderWrapper { } const source = new CancellationTokenSource(); - const dataOrThenable = this._provider.provideDecorations(uri, source.token); + const dataOrThenable = this.provider.provideDecorations(uri, source.token); if (!isThenable | undefined>(dataOrThenable)) { // sync -> we have a result now return this._keepItem(uri, dataOrThenable); @@ -325,7 +322,7 @@ class DecorationProviderWrapper { } } -export class FileDecorationsService implements IDecorationsService { +export class DecorationsService implements IDecorationsService { _serviceBrand: undefined; @@ -333,7 +330,6 @@ export class FileDecorationsService implements IDecorationsService { private readonly _onDidChangeDecorationsDelayed = new Emitter(); private readonly _onDidChangeDecorations = new Emitter(); private readonly _decorationStyles: DecorationStyles; - private readonly _disposables: IDisposable[]; readonly onDidChangeDecorations: Event = Event.any( this._onDidChangeDecorations.event, @@ -345,29 +341,25 @@ export class FileDecorationsService implements IDecorationsService { ); constructor( - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @ILogService private readonly _logService: ILogService, ) { 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(() => { + this.onDidChangeDecorations(() => { if (++count % 17 === 0) { this._decorationStyles.cleanUp(this._data.iterator()); } }); - - this._disposables = [ - reg, - this._decorationStyles - ]; } dispose(): void { - dispose(this._disposables); - dispose(this._onDidChangeDecorations); - dispose(this._onDidChangeDecorationsDelayed); + this._decorationStyles.dispose(); + this._onDidChangeDecorations.dispose(); + this._onDidChangeDecorationsDelayed.dispose(); } registerDecorationsProvider(provider: IDecorationsProvider): IDisposable { @@ -397,10 +389,12 @@ export class FileDecorationsService implements IDecorationsService { let data: IDecorationData[] = []; let containsChildren: boolean = false; for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { + const { label } = next.value.provider; next.value.getOrRetrieve(uri, includeChildren, (deco, isChild) => { if (!isChild || deco.bubble) { data.push(deco); containsChildren = isChild || containsChildren; + this._logService.trace('DecorationsService#getDecoration#getOrRetrieve', label, deco, isChild, uri); } }); } @@ -420,4 +414,4 @@ function getColor(theme: ITheme, color: string | undefined) { return 'inherit'; } -registerSingleton(IDecorationsService, FileDecorationsService); +registerSingleton(IDecorationsService, DecorationsService, true); 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 6975f0b64d3..2f1298ea85b 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -4,22 +4,23 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; +import { DecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; import { IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { ConsoleLogService } from 'vs/platform/log/common/log'; suite('DecorationsService', function () { - let service: FileDecorationsService; + let service: DecorationsService; setup(function () { if (service) { service.dispose(); } - service = new FileDecorationsService(new TestThemeService()); + service = new DecorationsService(new TestThemeService(), new ConsoleLogService()); }); test('Async provider, async/evented result', function () { From 904ab2364e78367ed6c82bcb91bd63b8cf54c384 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Oct 2019 12:58:09 +0200 Subject: [PATCH 195/435] in extension land prefer URI.isUri, fixes #81819 --- src/vs/workbench/api/common/extHost.api.impl.ts | 2 +- src/vs/workbench/api/common/extHostApiCommands.ts | 2 +- src/vs/workbench/api/common/extHostDiagnostics.ts | 2 +- src/vs/workbench/api/common/extHostQuickOpen.ts | 4 ++-- src/vs/workbench/api/common/extHostTreeViews.ts | 4 ++-- src/vs/workbench/api/common/extHostTypeConverters.ts | 2 +- src/vs/workbench/api/common/extHostTypes.ts | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 230d09a2903..2e8267a6b26 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -630,7 +630,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const options = uriOrFileNameOrOptions as { language?: string; content?: string; }; if (typeof uriOrFileNameOrOptions === 'string') { uriPromise = Promise.resolve(URI.file(uriOrFileNameOrOptions)); - } else if (uriOrFileNameOrOptions instanceof URI) { + } else if (URI.isUri(uriOrFileNameOrOptions)) { uriPromise = Promise.resolve(uriOrFileNameOrOptions); } else if (!options || typeof options === 'object') { uriPromise = extHostDocuments.createDocumentData(options); diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index e9022a259d5..1cf22a6fad6 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -239,7 +239,7 @@ export class ExtHostApiCommands { this._register(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute), { description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.', args: [ - { name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: (value: any) => value === undefined || value instanceof URI }, + { name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: (value: any) => value === undefined || URI.isUri(value) }, { name: 'options', description: '(optional) Options. Object with the following properties: `forceNewWindow `: Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window. `noRecentEntry`: Whether the opened URI will appear in the \'Open Recent\' list. Defaults to true. Note, for backward compatibility, options can also be of type boolean, representing the `forceNewWindow` setting.', constraint: (value: any) => value === undefined || typeof value === 'object' || typeof value === 'boolean' } ] }); diff --git a/src/vs/workbench/api/common/extHostDiagnostics.ts b/src/vs/workbench/api/common/extHostDiagnostics.ts index d654408346b..1455bb030d8 100644 --- a/src/vs/workbench/api/common/extHostDiagnostics.ts +++ b/src/vs/workbench/api/common/extHostDiagnostics.ts @@ -64,7 +64,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { this._checkDisposed(); let toSync: vscode.Uri[] = []; - if (first instanceof URI) { + if (URI.isUri(first)) { if (!diagnostics) { // remove this entry diff --git a/src/vs/workbench/api/common/extHostQuickOpen.ts b/src/vs/workbench/api/common/extHostQuickOpen.ts index 3d790f26276..c8587620994 100644 --- a/src/vs/workbench/api/common/extHostQuickOpen.ts +++ b/src/vs/workbench/api/common/extHostQuickOpen.ts @@ -455,7 +455,7 @@ function getIconUris(iconPath: QuickInputButton['iconPath']): { dark: URI, light function getLightIconUri(iconPath: QuickInputButton['iconPath']) { if (iconPath && !(iconPath instanceof ThemeIcon)) { if (typeof iconPath === 'string' - || iconPath instanceof URI) { + || URI.isUri(iconPath)) { return getIconUri(iconPath); } return getIconUri((iconPath as any).light); @@ -471,7 +471,7 @@ function getDarkIconUri(iconPath: QuickInputButton['iconPath']) { } function getIconUri(iconPath: string | URI) { - if (iconPath instanceof URI) { + if (URI.isUri(iconPath)) { return iconPath; } return URI.file(iconPath); diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index 7c462183bc7..95dc89564a1 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -540,7 +540,7 @@ class ExtHostTreeView extends Disposable { private getLightIconPath(extensionTreeItem: vscode.TreeItem): URI | undefined { if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon)) { if (typeof extensionTreeItem.iconPath === 'string' - || extensionTreeItem.iconPath instanceof URI) { + || URI.isUri(extensionTreeItem.iconPath)) { return this.getIconPath(extensionTreeItem.iconPath); } return this.getIconPath((<{ light: string | URI; dark: string | URI }>extensionTreeItem.iconPath).light); @@ -556,7 +556,7 @@ class ExtHostTreeView extends Disposable { } private getIconPath(iconPath: string | URI): URI { - if (iconPath instanceof URI) { + if (URI.isUri(iconPath)) { return iconPath; } return URI.file(iconPath); diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index dfce55ade92..0c9236b67af 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -291,7 +291,7 @@ export namespace MarkdownString { return part; } data = cloneAndChange(data, value => { - if (value instanceof URI) { + if (URI.isUri(value)) { const key = `__uri_${Math.random().toString(16).slice(2, 8)}`; bucket[key] = value; return key; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 981050bbef7..2324162060a 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1474,7 +1474,7 @@ export class DocumentLink { tooltip?: string; constructor(range: Range, target: URI | undefined) { - if (target && !(target instanceof URI)) { + if (target && !(URI.isUri(target))) { throw illegalArgument('target'); } if (!Range.isRange(range) || range.isEmpty) { @@ -2061,7 +2061,7 @@ export class TreeItem { constructor(label: string | vscode.TreeItemLabel, collapsibleState?: vscode.TreeItemCollapsibleState) constructor(resourceUri: URI, collapsibleState?: vscode.TreeItemCollapsibleState) constructor(arg1: string | vscode.TreeItemLabel | URI, public collapsibleState: vscode.TreeItemCollapsibleState = TreeItemCollapsibleState.None) { - if (arg1 instanceof URI) { + if (URI.isUri(arg1)) { this.resourceUri = arg1; } else { this.label = arg1; From d73a2f7a887d2697390751c64d3dd1ee888bab86 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Oct 2019 14:23:56 +0200 Subject: [PATCH 196/435] debt - less defense --- .../services/extensions/worker/extensionHostWorker.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 3b5706ce76a..748960c515e 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -35,9 +35,6 @@ self.postMessage = () => console.trace(`'postMessage' has been blocked`); const nativeAddEventLister = addEventListener.bind(self); self.addEventLister = () => console.trace(`'addEventListener' has been blocked`); -self.indexedDB.open = () => console.trace(`'indexedDB.open' has been blocked`); -self.caches.open = () => console.trace(`'indexedDB.caches' has been blocked`); - //#endregion --- const hostUtil = new class implements IHostUtils { From 56c472e18511f483d80cb8c1b8bd7b35c467a1af Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 08:36:02 +0200 Subject: [PATCH 197/435] strict init --- .../workbench/test/electron-browser/api/extHostSearch.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts b/src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts index 8dff457b408..bf71ebfaf5c 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts @@ -28,7 +28,7 @@ const disposables = new DisposableStore(); let mockMainThreadSearch: MockMainThreadSearch; class MockMainThreadSearch implements MainThreadSearchShape { - lastHandle: number; + lastHandle!: number; results: Array = []; From 93cfe48a3f00637eeb08acf1759a0735e7ead887 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 7 Oct 2019 09:25:12 +0200 Subject: [PATCH 198/435] Strict property initialization (#78168) --- .../base/browser/ui/findinput/replaceInput.ts | 175 +++++++++--------- src/vs/base/node/processes.ts | 1 + src/vs/editor/common/config/editorOptions.ts | 1 + .../quickOpen/quickOpenEditorWidget.ts | 7 +- src/vs/workbench/browser/contextkeys.ts | 67 ++++--- .../preferences/browser/keybindingWidgets.ts | 83 +++++---- .../services/remote/node/tunnelService.ts | 2 +- 7 files changed, 165 insertions(+), 171 deletions(-) diff --git a/src/vs/base/browser/ui/findinput/replaceInput.ts b/src/vs/base/browser/ui/findinput/replaceInput.ts index de448b6a484..5950e261de4 100644 --- a/src/vs/base/browser/ui/findinput/replaceInput.ts +++ b/src/vs/base/browser/ui/findinput/replaceInput.ts @@ -123,11 +123,96 @@ export class ReplaceInput extends Widget { this.inputValidationErrorBackground = options.inputValidationErrorBackground; this.inputValidationErrorForeground = options.inputValidationErrorForeground; + const history = options.history || []; const flexibleHeight = !!options.flexibleHeight; const flexibleWidth = !!options.flexibleWidth; const flexibleMaxHeight = options.flexibleMaxHeight; - this.buildDomNode(options.history || [], flexibleHeight, flexibleWidth, flexibleMaxHeight); + this.domNode = document.createElement('div'); + dom.addClass(this.domNode, 'monaco-findInput'); + + this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, { + ariaLabel: this.label || '', + placeholder: this.placeholder || '', + validationOptions: { + validation: this.validation + }, + inputBackground: this.inputBackground, + inputForeground: this.inputForeground, + inputBorder: this.inputBorder, + inputValidationInfoBackground: this.inputValidationInfoBackground, + inputValidationInfoForeground: this.inputValidationInfoForeground, + inputValidationInfoBorder: this.inputValidationInfoBorder, + inputValidationWarningBackground: this.inputValidationWarningBackground, + inputValidationWarningForeground: this.inputValidationWarningForeground, + inputValidationWarningBorder: this.inputValidationWarningBorder, + inputValidationErrorBackground: this.inputValidationErrorBackground, + inputValidationErrorForeground: this.inputValidationErrorForeground, + inputValidationErrorBorder: this.inputValidationErrorBorder, + history, + flexibleHeight, + flexibleWidth, + flexibleMaxHeight + })); + + this.preserveCase = this._register(new PreserveCaseCheckbox({ + appendTitle: '', + isChecked: false, + inputActiveOptionBorder: this.inputActiveOptionBorder, + inputActiveOptionBackground: this.inputActiveOptionBackground, + })); + this._register(this.preserveCase.onChange(viaKeyboard => { + this._onDidOptionChange.fire(viaKeyboard); + if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { + this.inputBox.focus(); + } + this.validate(); + })); + this._register(this.preserveCase.onKeyDown(e => { + this._onPreserveCaseKeyDown.fire(e); + })); + + if (this._showOptionButtons) { + this.cachedOptionsWidth = this.preserveCase.width(); + } else { + this.cachedOptionsWidth = 0; + } + + // Arrow-Key support to navigate between options + let indexes = [this.preserveCase.domNode]; + this.onkeydown(this.domNode, (event: IKeyboardEvent) => { + if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) { + let index = indexes.indexOf(document.activeElement); + if (index >= 0) { + let newIndex: number = -1; + if (event.equals(KeyCode.RightArrow)) { + newIndex = (index + 1) % indexes.length; + } else if (event.equals(KeyCode.LeftArrow)) { + if (index === 0) { + newIndex = indexes.length - 1; + } else { + newIndex = index - 1; + } + } + + if (event.equals(KeyCode.Escape)) { + indexes[index].blur(); + } else if (newIndex >= 0) { + indexes[newIndex].focus(); + } + + dom.EventHelper.stop(event, true); + } + } + }); + + + let controls = document.createElement('div'); + controls.className = 'controls'; + controls.style.display = this._showOptionButtons ? 'block' : 'none'; + controls.appendChild(this.preserveCase.domNode); + + this.domNode.appendChild(controls); if (parent) { parent.appendChild(this.domNode); @@ -256,94 +341,6 @@ export class ReplaceInput extends Widget { dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions)); } - private buildDomNode(history: string[], flexibleHeight: boolean, flexibleWidth: boolean, flexibleMaxHeight: number | undefined): void { - this.domNode = document.createElement('div'); - dom.addClass(this.domNode, 'monaco-findInput'); - - this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, { - ariaLabel: this.label || '', - placeholder: this.placeholder || '', - validationOptions: { - validation: this.validation - }, - inputBackground: this.inputBackground, - inputForeground: this.inputForeground, - inputBorder: this.inputBorder, - inputValidationInfoBackground: this.inputValidationInfoBackground, - inputValidationInfoForeground: this.inputValidationInfoForeground, - inputValidationInfoBorder: this.inputValidationInfoBorder, - inputValidationWarningBackground: this.inputValidationWarningBackground, - inputValidationWarningForeground: this.inputValidationWarningForeground, - inputValidationWarningBorder: this.inputValidationWarningBorder, - inputValidationErrorBackground: this.inputValidationErrorBackground, - inputValidationErrorForeground: this.inputValidationErrorForeground, - inputValidationErrorBorder: this.inputValidationErrorBorder, - history, - flexibleHeight, - flexibleWidth, - flexibleMaxHeight - })); - - this.preserveCase = this._register(new PreserveCaseCheckbox({ - appendTitle: '', - isChecked: false, - inputActiveOptionBorder: this.inputActiveOptionBorder, - inputActiveOptionBackground: this.inputActiveOptionBackground, - })); - this._register(this.preserveCase.onChange(viaKeyboard => { - this._onDidOptionChange.fire(viaKeyboard); - if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { - this.inputBox.focus(); - } - this.validate(); - })); - this._register(this.preserveCase.onKeyDown(e => { - this._onPreserveCaseKeyDown.fire(e); - })); - - if (this._showOptionButtons) { - this.cachedOptionsWidth = this.preserveCase.width(); - } else { - this.cachedOptionsWidth = 0; - } - - // Arrow-Key support to navigate between options - let indexes = [this.preserveCase.domNode]; - this.onkeydown(this.domNode, (event: IKeyboardEvent) => { - if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) { - let index = indexes.indexOf(document.activeElement); - if (index >= 0) { - let newIndex: number = -1; - if (event.equals(KeyCode.RightArrow)) { - newIndex = (index + 1) % indexes.length; - } else if (event.equals(KeyCode.LeftArrow)) { - if (index === 0) { - newIndex = indexes.length - 1; - } else { - newIndex = index - 1; - } - } - - if (event.equals(KeyCode.Escape)) { - indexes[index].blur(); - } else if (newIndex >= 0) { - indexes[newIndex].focus(); - } - - dom.EventHelper.stop(event, true); - } - } - }); - - - let controls = document.createElement('div'); - controls.className = 'controls'; - controls.style.display = this._showOptionButtons ? 'block' : 'none'; - controls.appendChild(this.preserveCase.domNode); - - this.domNode.appendChild(controls); - } - public validate(): void { if (this.inputBox) { this.inputBox.validate(); diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 5bee9f9eced..6b3376ec4f1 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -122,6 +122,7 @@ export abstract class AbstractProcess { } this.childProcess = null; + this.childProcessPromise = null; this.terminateRequested = false; if (this.options.env) { diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index f4c6c2df7f9..dde4e5888c9 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1954,6 +1954,7 @@ class EditorQuickSuggestions extends BaseEditorOption void, onCancel: () => void, onType: (value: string) => void, configuration: IQuickOpenEditorWidgetOptions, themeService: IThemeService) { this.codeEditor = codeEditor; this.themeService = themeService; + this.visible = false; - this.create(onOk, onCancel, onType, configuration); - } - - private create(onOk: () => void, onCancel: () => void, onType: (value: string) => void, configuration: IQuickOpenEditorWidgetOptions): void { this.domNode = document.createElement('div'); this.quickOpenWidget = new QuickOpenWidget( @@ -107,4 +104,4 @@ export class QuickOpenEditorWidget implements IOverlayWidget { return null; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 34640af8e1e..2a88e72a81c 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -88,41 +88,6 @@ export class WorkbenchContextKeysHandler extends Disposable { ) { super(); - this.initContextKeys(); - this.registerListeners(); - } - - private registerListeners(): void { - this.editorGroupService.whenRestored.then(() => this.updateEditorContextKeys()); - - this._register(this.editorService.onDidActiveEditorChange(() => this.updateEditorContextKeys())); - this._register(this.editorService.onDidVisibleEditorsChange(() => this.updateEditorContextKeys())); - - this._register(this.editorGroupService.onDidAddGroup(() => this.updateEditorContextKeys())); - this._register(this.editorGroupService.onDidRemoveGroup(() => this.updateEditorContextKeys())); - this._register(this.editorGroupService.onDidGroupIndexChange(() => this.updateEditorContextKeys())); - - this._register(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(), true)); - - this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateWorkbenchStateContextKey())); - this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.updateWorkspaceFolderCountContextKey())); - - this._register(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) { - this.updateSplitEditorsVerticallyContext(); - } - })); - - this._register(this.layoutService.onZenModeChange(enabled => this.inZenModeContext.set(enabled))); - this._register(this.layoutService.onFullscreenChange(fullscreen => this.isFullscreenContext.set(fullscreen))); - this._register(this.layoutService.onCenteredLayoutChange(centered => this.isCenteredLayoutContext.set(centered))); - this._register(this.layoutService.onPanelPositionChange(position => this.panelPositionContext.set(position))); - - this._register(this.viewletService.onDidViewletClose(() => this.updateSideBarContextKeys())); - this._register(this.viewletService.onDidViewletOpen(() => this.updateSideBarContextKeys())); - } - - private initContextKeys(): void { // Platform IsMacContext.bindTo(this.contextKeyService); @@ -187,6 +152,38 @@ export class WorkbenchContextKeysHandler extends Disposable { // Panel Position this.panelPositionContext = PanelPositionContext.bindTo(this.contextKeyService); this.panelPositionContext.set(this.layoutService.getPanelPosition() === Position.RIGHT ? 'right' : 'bottom'); + + this.registerListeners(); + } + + private registerListeners(): void { + this.editorGroupService.whenRestored.then(() => this.updateEditorContextKeys()); + + this._register(this.editorService.onDidActiveEditorChange(() => this.updateEditorContextKeys())); + this._register(this.editorService.onDidVisibleEditorsChange(() => this.updateEditorContextKeys())); + + this._register(this.editorGroupService.onDidAddGroup(() => this.updateEditorContextKeys())); + this._register(this.editorGroupService.onDidRemoveGroup(() => this.updateEditorContextKeys())); + this._register(this.editorGroupService.onDidGroupIndexChange(() => this.updateEditorContextKeys())); + + this._register(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(), true)); + + this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateWorkbenchStateContextKey())); + this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.updateWorkspaceFolderCountContextKey())); + + this._register(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) { + this.updateSplitEditorsVerticallyContext(); + } + })); + + this._register(this.layoutService.onZenModeChange(enabled => this.inZenModeContext.set(enabled))); + this._register(this.layoutService.onFullscreenChange(fullscreen => this.isFullscreenContext.set(fullscreen))); + this._register(this.layoutService.onCenteredLayoutChange(centered => this.isCenteredLayoutContext.set(centered))); + this._register(this.layoutService.onPanelPositionChange(position => this.panelPositionContext.set(position))); + + this._register(this.viewletService.onDidViewletClose(() => this.updateSideBarContextKeys())); + this._register(this.viewletService.onDidViewletOpen(() => this.updateSideBarContextKeys())); } private updateEditorContextKeys(): void { diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts b/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts index 81433e42323..dd0ea57af6d 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts @@ -59,6 +59,9 @@ export class KeybindingsSearchWidget extends SearchWidget { super(parent, options, contextViewService, instantiationService, themeService); this._register(attachInputBoxStyler(this.inputBox, themeService)); this._register(toDisposable(() => this.stopRecordingKeys())); + this._firstPart = null; + this._chordPart = null; + this._inputValue = ''; this._reset(); } @@ -166,7 +169,45 @@ export class DefineKeybindingWidget extends Widget { @IThemeService private readonly themeService: IThemeService ) { super(); - this.create(); + + this._domNode = createFastDomNode(document.createElement('div')); + this._domNode.setDisplay('none'); + this._domNode.setClassName('defineKeybindingWidget'); + this._domNode.setWidth(DefineKeybindingWidget.WIDTH); + this._domNode.setHeight(DefineKeybindingWidget.HEIGHT); + + const message = nls.localize('defineKeybinding.initial', "Press desired key combination and then press ENTER."); + dom.append(this._domNode.domNode, dom.$('.message', undefined, message)); + + this._register(attachStylerCallback(this.themeService, { editorWidgetBackground, editorWidgetForeground, widgetShadow }, colors => { + if (colors.editorWidgetBackground) { + this._domNode.domNode.style.backgroundColor = colors.editorWidgetBackground.toString(); + } else { + this._domNode.domNode.style.backgroundColor = null; + } + if (colors.editorWidgetForeground) { + this._domNode.domNode.style.color = colors.editorWidgetForeground.toString(); + } else { + this._domNode.domNode.style.color = null; + } + + if (colors.widgetShadow) { + this._domNode.domNode.style.boxShadow = `0 2px 8px ${colors.widgetShadow}`; + } else { + this._domNode.domNode.style.boxShadow = null; + } + })); + + this._keybindingInputWidget = this._register(this.instantiationService.createInstance(KeybindingsSearchWidget, this._domNode.domNode, { ariaLabel: message })); + this._keybindingInputWidget.startRecordingKeys(); + this._register(this._keybindingInputWidget.onKeybinding(keybinding => this.onKeybinding(keybinding))); + this._register(this._keybindingInputWidget.onEnter(() => this.hide())); + this._register(this._keybindingInputWidget.onEscape(() => this.onCancel())); + this._register(this._keybindingInputWidget.onBlur(() => this.onCancel())); + + this._outputNode = dom.append(this._domNode.domNode, dom.$('.output')); + this._showExistingKeybindingsNode = dom.append(this._domNode.domNode, dom.$('.existing')); + if (parent) { dom.append(parent, this._domNode.domNode); } @@ -217,46 +258,6 @@ export class DefineKeybindingWidget extends Widget { } } - private create(): void { - this._domNode = createFastDomNode(document.createElement('div')); - this._domNode.setDisplay('none'); - this._domNode.setClassName('defineKeybindingWidget'); - this._domNode.setWidth(DefineKeybindingWidget.WIDTH); - this._domNode.setHeight(DefineKeybindingWidget.HEIGHT); - - const message = nls.localize('defineKeybinding.initial', "Press desired key combination and then press ENTER."); - dom.append(this._domNode.domNode, dom.$('.message', undefined, message)); - - this._register(attachStylerCallback(this.themeService, { editorWidgetBackground, editorWidgetForeground, widgetShadow }, colors => { - if (colors.editorWidgetBackground) { - this._domNode.domNode.style.backgroundColor = colors.editorWidgetBackground.toString(); - } else { - this._domNode.domNode.style.backgroundColor = null; - } - if (colors.editorWidgetForeground) { - this._domNode.domNode.style.color = colors.editorWidgetForeground.toString(); - } else { - this._domNode.domNode.style.color = null; - } - - if (colors.widgetShadow) { - this._domNode.domNode.style.boxShadow = `0 2px 8px ${colors.widgetShadow}`; - } else { - this._domNode.domNode.style.boxShadow = null; - } - })); - - this._keybindingInputWidget = this._register(this.instantiationService.createInstance(KeybindingsSearchWidget, this._domNode.domNode, { ariaLabel: message })); - this._keybindingInputWidget.startRecordingKeys(); - this._register(this._keybindingInputWidget.onKeybinding(keybinding => this.onKeybinding(keybinding))); - this._register(this._keybindingInputWidget.onEnter(() => this.hide())); - this._register(this._keybindingInputWidget.onEscape(() => this.onCancel())); - this._register(this._keybindingInputWidget.onBlur(() => this.onCancel())); - - this._outputNode = dom.append(this._domNode.domNode, dom.$('.output')); - this._showExistingKeybindingsNode = dom.append(this._domNode.domNode, dom.$('.existing')); - } - private onKeybinding(keybinding: [ResolvedKeybinding | null, ResolvedKeybinding | null]): void { const [firstPart, chordPart] = keybinding; this._firstPart = firstPart; diff --git a/src/vs/workbench/services/remote/node/tunnelService.ts b/src/vs/workbench/services/remote/node/tunnelService.ts index 32273b70912..62b872ac8c9 100644 --- a/src/vs/workbench/services/remote/node/tunnelService.ts +++ b/src/vs/workbench/services/remote/node/tunnelService.ts @@ -26,7 +26,7 @@ export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemo class NodeRemoteTunnel extends Disposable implements RemoteTunnel { public readonly tunnelRemotePort: number; - public tunnelLocalPort: number; + public tunnelLocalPort!: number; private readonly _options: IConnectionOptions; private readonly _server: net.Server; From 6c9cf7692925e98cf4cc50459bd4e615c4553316 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 7 Oct 2019 09:58:03 +0200 Subject: [PATCH 199/435] Remove unused styling code --- .../preferences/browser/keybindingsEditorContribution.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts index 9b45e34dee4..dc77efc7ce5 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts @@ -23,13 +23,11 @@ import { parseTree, Node } from 'vs/base/common/json'; import { ScanCodeBinding } from 'vs/base/common/scanCode'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { WindowsNativeResolvedKeybinding } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper'; -import { themeColorFromId, ThemeColor, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService'; import { overviewRulerInfo, overviewRulerError } from 'vs/editor/common/view/editorColorRegistry'; import { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/model'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeybindingParser } from 'vs/base/common/keybindingParser'; -import Severity from 'vs/base/common/severity'; -import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); @@ -399,8 +397,3 @@ function isInterestingEditorModel(editor: ICodeEditor): boolean { registerEditorContribution(DefineKeybindingController); registerEditorCommand(new DefineKeybindingCommand()); - -registerThemingParticipant((theme, collector) => { - collector.addRule(`.monaco-editor .inlineKeybindingInfo:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Info, theme)}") -0.1em -0.2em no-repeat; }`); - collector.addRule(`.monaco-editor .inlineKeybindingError:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Error, theme)}") -0.1em -0.2em no-repeat; }`); -}); From 06c10cddf0633610f7554293cf15715c5c1fdc15 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 10:54:27 +0200 Subject: [PATCH 200/435] Strict init for tasks in extHostTypes.ts Part of #78168 --- src/vs/workbench/api/common/extHostTypes.ts | 28 ++++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 2324162060a..28b7f5ae205 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1626,6 +1626,7 @@ export class ProcessExecution implements vscode.ProcessExecution { if (typeof process !== 'string') { throw illegalArgument('process'); } + this._args = []; this._process = process; if (varg1 !== undefined) { if (Array.isArray(varg1)) { @@ -1635,9 +1636,6 @@ export class ProcessExecution implements vscode.ProcessExecution { this._options = varg1; } } - if (this._args === undefined) { - this._args = []; - } } @@ -1689,9 +1687,9 @@ export class ProcessExecution implements vscode.ProcessExecution { @es5ClassCompat export class ShellExecution implements vscode.ShellExecution { - private _commandLine: string; - private _command: string | vscode.ShellQuotedString; - private _args: (string | vscode.ShellQuotedString)[]; + private _commandLine: string | undefined; + private _command: string | vscode.ShellQuotedString | undefined; + private _args: (string | vscode.ShellQuotedString)[] = []; private _options: vscode.ShellExecutionOptions | undefined; constructor(commandLine: string, options?: vscode.ShellExecutionOptions); @@ -1717,7 +1715,7 @@ export class ShellExecution implements vscode.ShellExecution { } get commandLine(): string { - return this._commandLine; + return this._commandLine ? this._commandLine : ''; } set commandLine(value: string) { @@ -1728,7 +1726,7 @@ export class ShellExecution implements vscode.ShellExecution { } get command(): string | vscode.ShellQuotedString { - return this._command; + return this._command ? this._command : ''; } set command(value: string | vscode.ShellQuotedString) { @@ -1826,23 +1824,23 @@ export class Task implements vscode.Task2 { constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]); constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]); constructor(definition: vscode.TaskDefinition, arg2: string | (vscode.TaskScope.Global | vscode.TaskScope.Workspace) | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) { - this.definition = definition; + this._definition = this.definition = definition; let problemMatchers: string | string[]; if (typeof arg2 === 'string') { - this.name = arg2; - this.source = arg3; + this._name = this.name = arg2; + this._source = this.source = arg3; this.execution = arg4; problemMatchers = arg5; } else if (arg2 === TaskScope.Global || arg2 === TaskScope.Workspace) { this.target = arg2; - this.name = arg3; - this.source = arg4; + this._name = this.name = arg3; + this._source = this.source = arg4; this.execution = arg5; problemMatchers = arg6; } else { this.target = arg2; - this.name = arg3; - this.source = arg4; + this._name = this.name = arg3; + this._source = this.source = arg4; this.execution = arg5; problemMatchers = arg6; } From e9ee372447a8755b4046b66bae900b4d40777124 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 10:22:57 +0200 Subject: [PATCH 201/435] debt - reduce usage of strict null bypass --- src/vs/base/browser/ui/actionbar/actionbar.ts | 106 +++--- src/vs/base/browser/ui/checkbox/checkbox.ts | 4 +- src/vs/base/browser/ui/dialog/dialog.ts | 8 +- src/vs/base/browser/ui/inputbox/inputBox.ts | 6 +- src/vs/base/browser/ui/menu/menu.ts | 4 +- .../browser/ui/progressbar/progressbar.ts | 12 +- src/vs/base/node/encoding.ts | 6 +- src/vs/base/node/pfs.ts | 2 +- src/vs/base/node/zip.ts | 2 +- .../quickopen/browser/quickOpenWidget.ts | 15 + src/vs/base/parts/storage/node/storage.ts | 14 +- src/vs/code/browser/workbench/workbench.ts | 10 +- src/vs/code/electron-main/app.ts | 2 +- src/vs/code/electron-main/window.ts | 325 ++++++++---------- .../quickOpen/quickOpenEditorWidget.ts | 20 +- .../browser/menuEntryActionViewItem.ts | 25 +- .../backup/electron-main/backupMainService.ts | 9 +- .../electron-main/electronMainService.ts | 2 +- .../launch/electron-main/launchMainService.ts | 7 +- .../platform/menubar/electron-main/menubar.ts | 11 +- .../platform/windows/electron-main/windows.ts | 11 +- .../electron-main/windowsMainService.ts | 20 +- .../electron-main/workspacesMainService.ts | 9 +- .../electron-main/workspacesService.ts | 2 +- src/vs/workbench/browser/actions.ts | 16 +- .../browser/actions/layoutActions.ts | 2 +- .../browser/actions/navigationActions.ts | 14 +- src/vs/workbench/browser/composite.ts | 6 +- src/vs/workbench/browser/dnd.ts | 12 +- src/vs/workbench/browser/labels.ts | 8 +- src/vs/workbench/browser/layout.ts | 2 +- .../workbench/browser/parts/compositeBar.ts | 15 +- .../browser/parts/compositeBarActions.ts | 46 ++- .../workbench/browser/parts/compositePart.ts | 6 +- .../browser/parts/editor/editorActions.ts | 2 +- .../browser/parts/editor/editorDropTarget.ts | 125 ++++--- .../browser/parts/editor/editorStatus.ts | 10 +- .../browser/parts/editor/tabsTitleControl.ts | 129 ++++--- .../browser/parts/editor/textEditor.ts | 2 +- .../browser/parts/editor/titleControl.ts | 4 +- .../parts/notifications/notificationsList.ts | 2 +- .../browser/parts/panel/panelPart.ts | 4 +- .../browser/parts/sidebar/sidebarPart.ts | 13 +- .../browser/parts/statusbar/statusbarPart.ts | 16 +- .../browser/parts/titlebar/menubarControl.ts | 9 +- .../browser/parts/titlebar/titlebarPart.ts | 12 +- src/vs/workbench/common/contributions.ts | 6 +- .../common/editor/binaryEditorModel.ts | 3 +- .../common/editor/textDiffEditorModel.ts | 4 +- src/vs/workbench/common/resources.ts | 14 +- .../comments/browser/reactionsAction.ts | 4 + .../extensions/browser/extensionsActions.ts | 4 +- .../contrib/files/browser/views/emptyView.ts | 4 +- .../contrib/scm/browser/mainPanel.ts | 2 +- src/vs/workbench/electron-browser/window.ts | 8 +- .../dialogs/browser/simpleFileDialog.ts | 2 +- .../electron-browser/fileDialogService.ts | 10 +- .../services/editor/browser/editorService.ts | 5 +- .../services/history/browser/history.ts | 8 +- .../common/textFileEditorModelManager.ts | 8 +- .../electron-browser/nativeTextFileService.ts | 2 +- 61 files changed, 662 insertions(+), 509 deletions(-) diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 43c76fb28d4..27925b09b9c 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -33,11 +33,12 @@ export interface IBaseActionViewItemOptions { export class BaseActionViewItem extends Disposable implements IActionViewItem { - element?: HTMLElement; + element: HTMLElement | undefined; + _context: any; _action: IAction; - private _actionRunner!: IActionRunner; + private _actionRunner: IActionRunner | undefined; constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) { super(); @@ -81,12 +82,16 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem { } } - set actionRunner(actionRunner: IActionRunner) { - this._actionRunner = actionRunner; + get actionRunner(): IActionRunner { + if (!this._actionRunner) { + this._actionRunner = this._register(new ActionRunner()); + } + + return this._actionRunner; } - get actionRunner(): IActionRunner { - return this._actionRunner; + set actionRunner(actionRunner: IActionRunner) { + this._actionRunner = actionRunner; } getAction(): IAction { @@ -102,7 +107,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem { } render(container: HTMLElement): void { - this.element = container; + const element = this.element = container; this._register(Gesture.addTarget(container)); const enableDragging = this.options && this.options.draggable; @@ -110,19 +115,19 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem { container.draggable = true; } - this._register(DOM.addDisposableListener(this.element, EventType.Tap, e => this.onClick(e))); + this._register(DOM.addDisposableListener(element, EventType.Tap, e => this.onClick(e))); - this._register(DOM.addDisposableListener(this.element, DOM.EventType.MOUSE_DOWN, e => { + this._register(DOM.addDisposableListener(element, DOM.EventType.MOUSE_DOWN, e => { if (!enableDragging) { DOM.EventHelper.stop(e, true); // do not run when dragging is on because that would disable it } - if (this._action.enabled && e.button === 0 && this.element) { - DOM.addClass(this.element, 'active'); + if (this._action.enabled && e.button === 0) { + DOM.addClass(element, 'active'); } })); - this._register(DOM.addDisposableListener(this.element, DOM.EventType.CLICK, e => { + this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, e => { DOM.EventHelper.stop(e, true); // See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard // > Writing to the clipboard @@ -139,14 +144,14 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem { } })); - this._register(DOM.addDisposableListener(this.element, DOM.EventType.DBLCLICK, e => { + this._register(DOM.addDisposableListener(element, DOM.EventType.DBLCLICK, e => { DOM.EventHelper.stop(e, true); })); [DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT].forEach(event => { - this._register(DOM.addDisposableListener(this.element!, event, e => { + this._register(DOM.addDisposableListener(element, event, e => { DOM.EventHelper.stop(e); - DOM.removeClass(this.element!, 'active'); + DOM.removeClass(element, 'active'); })); }); } @@ -165,7 +170,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem { } } - this._actionRunner.run(this._action, context); + this.actionRunner.run(this._action, context); } focus(): void { @@ -232,7 +237,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions { export class ActionViewItem extends BaseActionViewItem { - protected label!: HTMLElement; + protected label: HTMLElement | undefined; protected options: IActionViewItemOptions; private cssClass?: string; @@ -252,13 +257,17 @@ export class ActionViewItem extends BaseActionViewItem { if (this.element) { this.label = DOM.append(this.element, DOM.$('a.action-label')); } - if (this._action.id === Separator.ID) { - this.label.setAttribute('role', 'presentation'); // A separator is a presentation item - } else { - if (this.options.isMenu) { - this.label.setAttribute('role', 'menuitem'); + + + if (this.label) { + if (this._action.id === Separator.ID) { + this.label.setAttribute('role', 'presentation'); // A separator is a presentation item } else { - this.label.setAttribute('role', 'button'); + if (this.options.isMenu) { + this.label.setAttribute('role', 'menuitem'); + } else { + this.label.setAttribute('role', 'button'); + } } } @@ -276,11 +285,13 @@ export class ActionViewItem extends BaseActionViewItem { focus(): void { super.focus(); - this.label.focus(); + if (this.label) { + this.label.focus(); + } } updateLabel(): void { - if (this.options.label) { + if (this.options.label && this.label) { this.label.textContent = this.getAction().label; } } @@ -299,52 +310,65 @@ export class ActionViewItem extends BaseActionViewItem { } } - if (title) { + if (title && this.label) { this.label.title = title; } } updateClass(): void { - if (this.cssClass) { + if (this.cssClass && this.label) { DOM.removeClasses(this.label, this.cssClass); } if (this.options.icon) { this.cssClass = this.getAction().class; - DOM.addClass(this.label, 'codicon'); - if (this.cssClass) { - DOM.addClasses(this.label, this.cssClass); + + if (this.label) { + DOM.addClass(this.label, 'codicon'); + if (this.cssClass) { + DOM.addClasses(this.label, this.cssClass); + } } this.updateEnabled(); } else { - DOM.removeClass(this.label, 'codicon'); + if (this.label) { + DOM.removeClass(this.label, 'codicon'); + } } } updateEnabled(): void { if (this.getAction().enabled) { - this.label.removeAttribute('aria-disabled'); + if (this.label) { + this.label.removeAttribute('aria-disabled'); + DOM.removeClass(this.label, 'disabled'); + this.label.tabIndex = 0; + } + if (this.element) { DOM.removeClass(this.element, 'disabled'); } - DOM.removeClass(this.label, 'disabled'); - this.label.tabIndex = 0; } else { - this.label.setAttribute('aria-disabled', 'true'); + if (this.label) { + this.label.setAttribute('aria-disabled', 'true'); + DOM.addClass(this.label, 'disabled'); + DOM.removeTabIndexAndUpdateFocus(this.label); + } + if (this.element) { DOM.addClass(this.element, 'disabled'); } - DOM.addClass(this.label, 'disabled'); - DOM.removeTabIndexAndUpdateFocus(this.label); } } updateChecked(): void { - if (this.getAction().checked) { - DOM.addClass(this.label, 'checked'); - } else { - DOM.removeClass(this.label, 'checked'); + if (this.label) { + if (this.getAction().checked) { + DOM.addClass(this.label, 'checked'); + } else { + DOM.removeClass(this.label, 'checked'); + } } } } diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index e5f64f9174c..afc9cc616a0 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -38,7 +38,7 @@ const defaultOpts = { export class CheckboxActionViewItem extends BaseActionViewItem { - private checkbox!: Checkbox; + private checkbox: Checkbox | undefined; private readonly disposables = new DisposableStore(); render(container: HTMLElement): void { @@ -51,7 +51,7 @@ export class CheckboxActionViewItem extends BaseActionViewItem { title: this._action.label }); this.disposables.add(this.checkbox); - this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox!.checked, this)); + this.disposables.add(this.checkbox.onChange(() => this._action.checked = !!this.checkbox && this.checkbox.checked, this)); this.element.appendChild(this.checkbox.domNode); } diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index b3c43c0794c..9be85097748 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -142,7 +142,9 @@ export class Dialog extends Disposable { let eventHandled = false; if (evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) { if (!this.checkboxHasFocus && focusedButton === 0) { - this.checkbox!.domNode.focus(); + if (this.checkbox) { + this.checkbox.domNode.focus(); + } this.checkboxHasFocus = true; } else { focusedButton = (this.checkboxHasFocus ? 0 : focusedButton) + buttonGroup.buttons.length - 1; @@ -154,7 +156,9 @@ export class Dialog extends Disposable { eventHandled = true; } else if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) { if (!this.checkboxHasFocus && focusedButton === buttonGroup.buttons.length - 1) { - this.checkbox!.domNode.focus(); + if (this.checkbox) { + this.checkbox.domNode.focus(); + } this.checkboxHasFocus = true; } else { focusedButton = this.checkboxHasFocus ? 0 : focusedButton + 1; diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index d7d3b1217b0..d743e3bf9f2 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -351,7 +351,7 @@ export class InputBox extends Widget { } private updateScrollDimensions(): void { - if (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number') { + if (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number' || !this.scrollableElement) { return; } @@ -359,8 +359,8 @@ export class InputBox extends Widget { const height = this.cachedHeight; const scrollTop = this.input.scrollTop; - this.scrollableElement!.setScrollDimensions({ scrollHeight, height }); - this.scrollableElement!.setScrollPosition({ scrollTop }); + this.scrollableElement.setScrollDimensions({ scrollHeight, height }); + this.scrollableElement.setScrollPosition({ scrollTop }); } public showMessage(message: IMessage, force?: boolean): void { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 41ccd8fffc2..b81aee160eb 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -818,7 +818,9 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem { class MenuSeparatorActionViewItem extends ActionViewItem { style(style: IMenuStyles): void { - this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : null; + if (this.label) { + this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : null; + } } } diff --git a/src/vs/base/browser/ui/progressbar/progressbar.ts b/src/vs/base/browser/ui/progressbar/progressbar.ts index 405bfe80c05..19e16dfbe87 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.ts +++ b/src/vs/base/browser/ui/progressbar/progressbar.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./progressbar'; -import * as assert from 'vs/base/common/assert'; import { Disposable } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; @@ -154,9 +153,7 @@ export class ProgressBar extends Disposable { * Tells the progress bar that an increment of work has been completed. */ worked(value: number): ProgressBar { - value = Number(value); - assert.ok(!isNaN(value), 'Value is not a number'); - value = Math.max(1, value); + value = Math.max(1, Number(value)); return this.doSetWorked(this.workedVal + value); } @@ -165,16 +162,13 @@ export class ProgressBar extends Disposable { * Tells the progress bar the total amount of work that has been completed. */ setWorked(value: number): ProgressBar { - value = Number(value); - assert.ok(!isNaN(value), 'Value is not a number'); - value = Math.max(1, value); + value = Math.max(1, Number(value)); return this.doSetWorked(value); } private doSetWorked(value: number): ProgressBar { - assert.ok(isNumber(this.totalWork), 'Total work not set'); - const totalWork = this.totalWork!; + const totalWork = this.totalWork || 100; this.workedVal = value; this.workedVal = Math.min(totalWork, this.workedVal); diff --git a/src/vs/base/node/encoding.ts b/src/vs/base/node/encoding.ts index 83428b3590c..f079038301c 100644 --- a/src/vs/base/node/encoding.ts +++ b/src/vs/base/node/encoding.ts @@ -122,7 +122,11 @@ export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions // detection. thus, wrap up starting the stream even // without all the data to get things going else { - this._startDecodeStream(() => this.decodeStream!.end(callback)); + this._startDecodeStream(() => { + if (this.decodeStream) { + this.decodeStream.end(callback); + } + }); } } }; diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 14dca3d5f49..e08289bdce4 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -679,4 +679,4 @@ const WIN32_MAX_HEAP_SIZE = 700 * 1024 * 1024; // 700 MB const GENERAL_MAX_HEAP_SIZE = 700 * 2 * 1024 * 1024; // 1400 MB export const MAX_FILE_SIZE = process.arch === 'ia32' ? WIN32_MAX_FILE_SIZE : GENERAL_MAX_FILE_SIZE; -export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE; \ No newline at end of file +export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE; diff --git a/src/vs/base/node/zip.ts b/src/vs/base/node/zip.ts index 3c474dc0343..17080402e6a 100644 --- a/src/vs/base/node/zip.ts +++ b/src/vs/base/node/zip.ts @@ -156,7 +156,7 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, tok const stream = openZipStream(zipfile, entry); const mode = modeFromEntry(entry); - last = createCancelablePromise(token => throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options, token).then(() => readNextEntry(token)))).then(null!, e)); + last = createCancelablePromise(token => throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options, token).then(() => readNextEntry(token)))).then(null, e)); }); }); } diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 68be9fba510..f5276b7baa3 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -99,25 +99,40 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { private isDisposed: boolean; private options: IQuickOpenOptions; + // @ts-ignore (legacy widget - to be replaced with quick input) private element: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private tree: ITree; + // @ts-ignore (legacy widget - to be replaced with quick input) private inputBox: InputBox; + // @ts-ignore (legacy widget - to be replaced with quick input) private inputContainer: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private helpText: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private resultCount: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private treeContainer: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private progressBar: ProgressBar; + // @ts-ignore (legacy widget - to be replaced with quick input) private visible: boolean; + // @ts-ignore (legacy widget - to be replaced with quick input) private isLoosingFocus: boolean; private callbacks: IQuickOpenCallbacks; private quickNavigateConfiguration: IQuickNavigateConfiguration | undefined; private container: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private treeElement: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private inputElement: HTMLElement; + // @ts-ignore (legacy widget - to be replaced with quick input) private layoutDimensions: DOM.Dimension; private model: IModel | null; private inputChangingTimeoutHandle: any; + // @ts-ignore (legacy widget - to be replaced with quick input) private styles: IQuickOpenStyles; + // @ts-ignore (legacy widget - to be replaced with quick input) private renderer: Renderer; constructor(container: HTMLElement, callbacks: IQuickOpenCallbacks, options: IQuickOpenOptions) { diff --git a/src/vs/base/parts/storage/node/storage.ts b/src/vs/base/parts/storage/node/storage.ts index 85a3ef2d9ac..5042879c655 100644 --- a/src/vs/base/parts/storage/node/storage.ts +++ b/src/vs/base/parts/storage/node/storage.ts @@ -82,16 +82,18 @@ export class SQLiteStorageDatabase implements IStorageDatabase { } return this.transaction(connection, () => { + const toInsert = request.insert; + const toDelete = request.delete; // INSERT - if (request.insert && request.insert.size > 0) { + if (toInsert && toInsert.size > 0) { const keysValuesChunks: (string[])[] = []; keysValuesChunks.push([]); // seed with initial empty chunk // Split key/values into chunks of SQLiteStorageDatabase.MAX_HOST_PARAMETERS // so that we can efficiently run the INSERT with as many HOST parameters as possible let currentChunkIndex = 0; - request.insert.forEach((value, key) => { + toInsert.forEach((value, key) => { let keyValueChunk = keysValuesChunks[currentChunkIndex]; if (keyValueChunk.length > SQLiteStorageDatabase.MAX_HOST_PARAMETERS) { @@ -107,7 +109,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase { this.prepare(connection, `INSERT INTO ItemTable VALUES ${fill(keysValuesChunk.length / 2, '(?,?)').join(',')}`, stmt => stmt.run(keysValuesChunk), () => { const keys: string[] = []; let length = 0; - request.insert!.forEach((value, key) => { + toInsert.forEach((value, key) => { keys.push(key); length += value.length; }); @@ -118,7 +120,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase { } // DELETE - if (request.delete && request.delete.size) { + if (toDelete && toDelete.size) { const keysChunks: (string[])[] = []; keysChunks.push([]); // seed with initial empty chunk @@ -126,7 +128,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase { // so that we can efficiently run the DELETE with as many HOST parameters // as possible let currentChunkIndex = 0; - request.delete.forEach(key => { + toDelete.forEach(key => { let keyChunk = keysChunks[currentChunkIndex]; if (keyChunk.length > SQLiteStorageDatabase.MAX_HOST_PARAMETERS) { @@ -141,7 +143,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase { keysChunks.forEach(keysChunk => { this.prepare(connection, `DELETE FROM ItemTable WHERE key IN (${fill(keysChunk.length, '?').join(',')})`, stmt => stmt.run(keysChunk), () => { const keys: string[] = []; - request.delete!.forEach(key => { + toDelete.forEach(key => { keys.push(key); }); diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 037e85ba25f..60e7d9a3ecc 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -22,7 +22,7 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider { static readonly CREDENTIALS_OPENED_KEY = 'credentials.provider'; - private _credentials!: ICredential[]; + private _credentials: ICredential[] | undefined; private get credentials(): ICredential[] { if (!this._credentials) { try { @@ -250,7 +250,13 @@ class WorkspaceProvider implements IWorkspaceProvider { } } -const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(document.getElementById('vscode-workbench-web-configuration')!.getAttribute('data-settings')!); +const configElement = document.getElementById('vscode-workbench-web-configuration'); +const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined; +if (!configElement || !configElementAttribute) { + throw new Error('Missing web configuration element'); +} + +const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute); options.workspaceProvider = new WorkspaceProvider(options.folderUri ? { folderUri: URI.revive(options.folderUri) } : options.workspaceUri ? { workspaceUri: URI.revive(options.workspaceUri) } : undefined); options.urlCallbackProvider = new PollingURLCallbackProvider(); options.credentialsProvider = new LocalStorageCredentialsProvider(); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 9608d2fa10d..368d7b42f3a 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -376,7 +376,7 @@ export class CodeApplication extends Disposable { // Create driver if (this.environmentService.driverHandle) { - const server = await serveDriver(electronIpcServer, this.environmentService.driverHandle!, this.environmentService, appInstantiationService); + const server = await serveDriver(electronIpcServer, this.environmentService.driverHandle, this.environmentService, appInstantiationService); this.logService.info('Driver started at:', this.environmentService.driverHandle); this._register(server); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index b3c2af9cc48..f8bb5b22c9a 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -73,19 +73,16 @@ export class CodeWindow extends Disposable implements ICodeWindow { private readonly _onLoad = this._register(new Emitter()); readonly onLoad: CommonEvent = this._onLoad.event; - private hiddenTitleBarStyle: boolean; - private showTimeoutHandle: NodeJS.Timeout; - private _id: number; - private _win: BrowserWindow; + private hiddenTitleBarStyle: boolean | undefined; + private showTimeoutHandle: NodeJS.Timeout | undefined; private _lastFocusTime: number; private _readyState: ReadyState; private windowState: IWindowState; - private currentMenuBarVisibility: MenuBarVisibility; - private representedFilename: string; + private currentMenuBarVisibility: MenuBarVisibility | undefined; + private representedFilename: string | undefined; private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[]; - private currentConfig: IWindowConfiguration; private pendingLoadConfig?: IWindowConfiguration; private marketplaceHeadersPromise: Promise; @@ -111,8 +108,111 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._readyState = ReadyState.NONE; this.whenReadyCallbacks = []; - // create browser window - this.createBrowserWindow(config); + //#region create browser window + { + // Load window state + const [state, hasMultipleDisplays] = this.restoreWindowState(config.state); + this.windowState = state; + + // in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below) + const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen); + + const options: BrowserWindowConstructorOptions = { + width: this.windowState.width, + height: this.windowState.height, + x: this.windowState.x, + y: this.windowState.y, + backgroundColor: this.themeMainService.getBackgroundColor(), + minWidth: CodeWindow.MIN_WIDTH, + minHeight: CodeWindow.MIN_HEIGHT, + show: !isFullscreenOrMaximized, + title: product.nameLong, + webPreferences: { + // By default if Code is in the background, intervals and timeouts get throttled, so we + // want to enforce that Code stays in the foreground. This triggers a disable_hidden_ + // flag that Electron provides via patch: + // https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch + backgroundThrottling: false, + nodeIntegration: true, + nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER, + webviewTag: true + } + }; + + if (isLinux) { + options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s) + } + + const windowConfig = this.configurationService.getValue('window'); + + if (isMacintosh && !this.useNativeFullScreen()) { + options.fullscreenable = false; // enables simple fullscreen mode + } + + if (isMacintosh) { + options.acceptFirstMouse = true; // enabled by default + + if (windowConfig && windowConfig.clickThroughInactive === false) { + options.acceptFirstMouse = false; + } + } + + const useNativeTabs = isMacintosh && windowConfig && windowConfig.nativeTabs === true; + if (useNativeTabs) { + options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs + } + + const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom'; + if (useCustomTitleStyle) { + options.titleBarStyle = 'hidden'; + this.hiddenTitleBarStyle = true; + if (!isMacintosh) { + options.frame = false; + } + } + + // Create the browser window. + this._win = new BrowserWindow(options); + this._id = this._win.id; + + if (isMacintosh && useCustomTitleStyle) { + this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any + } + + // TODO@Ben (Electron 4 regression): when running on multiple displays where the target display + // to open the window has a larger resolution than the primary display, the window will not size + // correctly unless we set the bounds again (https://github.com/microsoft/vscode/issues/74872) + // + // However, when running with native tabs with multiple windows we cannot use this workaround + // because there is a potential that the new window will be added as native tab instead of being + // a window on its own. In that case calling setBounds() would cause https://github.com/microsoft/vscode/issues/75830 + if (isMacintosh && hasMultipleDisplays && (!useNativeTabs || BrowserWindow.getAllWindows().length === 1)) { + if ([this.windowState.width, this.windowState.height, this.windowState.x, this.windowState.y].every(value => typeof value === 'number')) { + const ensuredWindowState = this.windowState as Required; + this._win.setBounds({ + width: ensuredWindowState.width, + height: ensuredWindowState.height, + x: ensuredWindowState.x, + y: ensuredWindowState.y + }); + } + } + + if (isFullscreenOrMaximized) { + this._win.maximize(); + + if (this.windowState.mode === WindowMode.Fullscreen) { + this.setFullScreen(true); + } + + if (!this._win.isVisible()) { + this._win.show(); // to reduce flicker from the default window size to maximize, we only show after maximize + } + } + + this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too + } + //#endregion // respect configured menu bar visibility this.onConfigurationUpdated(); @@ -121,139 +221,26 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.createTouchBar(); // Request handling - this.handleMarketplaceRequests(); + this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentService, this.fileService); // Eventing this.registerListeners(); } - private createBrowserWindow(config: IWindowCreationOptions): void { + private currentConfig: IWindowConfiguration | undefined; + get config(): IWindowConfiguration | undefined { return this.currentConfig; } - // Load window state - const [state, hasMultipleDisplays] = this.restoreWindowState(config.state); - this.windowState = state; + private _id: number; + get id(): number { return this._id; } - // in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below) - const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen); + private _win: BrowserWindow; + get win(): BrowserWindow { return this._win; } - const options: BrowserWindowConstructorOptions = { - width: this.windowState.width, - height: this.windowState.height, - x: this.windowState.x, - y: this.windowState.y, - backgroundColor: this.themeMainService.getBackgroundColor(), - minWidth: CodeWindow.MIN_WIDTH, - minHeight: CodeWindow.MIN_HEIGHT, - show: !isFullscreenOrMaximized, - title: product.nameLong, - webPreferences: { - // By default if Code is in the background, intervals and timeouts get throttled, so we - // want to enforce that Code stays in the foreground. This triggers a disable_hidden_ - // flag that Electron provides via patch: - // https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch - backgroundThrottling: false, - nodeIntegration: true, - nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER, - webviewTag: true - } - }; + get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; } - if (isLinux) { - options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s) - } + get isExtensionDevelopmentHost(): boolean { return !!(this.config && this.config.extensionDevelopmentPath); } - const windowConfig = this.configurationService.getValue('window'); - - if (isMacintosh && !this.useNativeFullScreen()) { - options.fullscreenable = false; // enables simple fullscreen mode - } - - if (isMacintosh) { - options.acceptFirstMouse = true; // enabled by default - - if (windowConfig && windowConfig.clickThroughInactive === false) { - options.acceptFirstMouse = false; - } - } - - const useNativeTabs = isMacintosh && windowConfig && windowConfig.nativeTabs === true; - if (useNativeTabs) { - options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs - } - - const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom'; - if (useCustomTitleStyle) { - options.titleBarStyle = 'hidden'; - this.hiddenTitleBarStyle = true; - if (!isMacintosh) { - options.frame = false; - } - } - - // Create the browser window. - this._win = new BrowserWindow(options); - this._id = this._win.id; - - if (isMacintosh && useCustomTitleStyle) { - this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any - } - - // TODO@Ben (Electron 4 regression): when running on multiple displays where the target display - // to open the window has a larger resolution than the primary display, the window will not size - // correctly unless we set the bounds again (https://github.com/microsoft/vscode/issues/74872) - // - // However, when running with native tabs with multiple windows we cannot use this workaround - // because there is a potential that the new window will be added as native tab instead of being - // a window on its own. In that case calling setBounds() would cause https://github.com/microsoft/vscode/issues/75830 - if (isMacintosh && hasMultipleDisplays && (!useNativeTabs || BrowserWindow.getAllWindows().length === 1)) { - if ([this.windowState.width, this.windowState.height, this.windowState.x, this.windowState.y].every(value => typeof value === 'number')) { - this._win.setBounds({ - width: this.windowState.width!, - height: this.windowState.height!, - x: this.windowState.x!, - y: this.windowState.y! - }); - } - } - - if (isFullscreenOrMaximized) { - this._win.maximize(); - - if (this.windowState.mode === WindowMode.Fullscreen) { - this.setFullScreen(true); - } - - if (!this._win.isVisible()) { - this._win.show(); // to reduce flicker from the default window size to maximize, we only show after maximize - } - } - - this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too - } - - hasHiddenTitleBarStyle(): boolean { - return this.hiddenTitleBarStyle; - } - - get isExtensionDevelopmentHost(): boolean { - return !!this.config.extensionDevelopmentPath; - } - - get isExtensionTestHost(): boolean { - return !!this.config.extensionTestsPath; - } - - get config(): IWindowConfiguration { - return this.currentConfig; - } - - get id(): number { - return this._id; - } - - get win(): BrowserWindow { - return this._win; - } + get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); } setRepresentedFilename(filename: string): void { if (isMacintosh) { @@ -263,7 +250,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } } - getRepresentedFilename(): string { + getRepresentedFilename(): string | undefined { if (isMacintosh) { return this.win.getRepresentedFilename(); } @@ -283,25 +270,15 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._win.focus(); } - get lastFocusTime(): number { - return this._lastFocusTime; - } + get lastFocusTime(): number { return this._lastFocusTime; } - get backupPath(): string | undefined { - return this.currentConfig ? this.currentConfig.backupPath : undefined; - } + get backupPath(): string | undefined { return this.currentConfig ? this.currentConfig.backupPath : undefined; } - get openedWorkspace(): IWorkspaceIdentifier | undefined { - return this.currentConfig ? this.currentConfig.workspace : undefined; - } + get openedWorkspace(): IWorkspaceIdentifier | undefined { return this.currentConfig ? this.currentConfig.workspace : undefined; } - get openedFolderUri(): URI | undefined { - return this.currentConfig ? this.currentConfig.folderUri : undefined; - } + get openedFolderUri(): URI | undefined { return this.currentConfig ? this.currentConfig.folderUri : undefined; } - get remoteAuthority(): string | undefined { - return this.currentConfig ? this.currentConfig.remoteAuthority : undefined; - } + get remoteAuthority(): string | undefined { return this.currentConfig ? this.currentConfig.remoteAuthority : undefined; } setReady(): void { this._readyState = ReadyState.READY; @@ -342,24 +319,6 @@ export class CodeWindow extends Disposable implements ICodeWindow { }); } - private handleMarketplaceRequests(): void { - - // Resolve marketplace headers - this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentService, this.fileService); - - // Inject headers when requests are incoming - const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*']; - this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => { - this.marketplaceHeadersPromise.then(headers => { - const requestHeaders = objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined }; - if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) { - requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`; - } - cb({ cancel: false, requestHeaders }); - }); - }); - } - private registerListeners(): void { // Crashes & Unrsponsive @@ -422,7 +381,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { return; // disposed } - if (!this.useNativeFullScreen() && this.isFullScreen()) { + if (!this.useNativeFullScreen() && this.isFullScreen) { this.setFullScreen(false); this.setFullScreen(true); } @@ -476,6 +435,18 @@ export class CodeWindow extends Disposable implements ICodeWindow { // Handle Workspace events this._register(this.workspacesMainService.onUntitledWorkspaceDeleted(e => this.onUntitledWorkspaceDeleted(e))); + + // Inject headers when requests are incoming + const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*']; + this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => { + this.marketplaceHeadersPromise.then(headers => { + const requestHeaders = objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined }; + if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) { + requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`; + } + cb({ cancel: false, requestHeaders }); + }); + }); } private onWindowError(error: WindowError): void { @@ -554,7 +525,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { // Make sure to update our workspace config if we detect that it // was deleted - if (this.openedWorkspace && this.openedWorkspace.id === workspace.id) { + if (this.openedWorkspace && this.openedWorkspace.id === workspace.id && this.currentConfig) { this.currentConfig.workspace = undefined; } } @@ -674,7 +645,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } // Set fullscreen state - windowConfiguration.fullscreen = this.isFullScreen(); + windowConfiguration.fullscreen = this.isFullScreen; // Set Accessibility Config let autoDetectHighContrast = true; @@ -686,7 +657,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { // Title style related windowConfiguration.maximized = this._win.isMaximized(); - windowConfiguration.frameless = this.hasHiddenTitleBarStyle() && !isMacintosh; + windowConfiguration.frameless = this.hasHiddenTitleBarStyle && !isMacintosh; // Dump Perf Counters windowConfiguration.perfEntries = perf.exportEntries(); @@ -732,7 +703,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } // fullscreen gets special treatment - if (this.isFullScreen()) { + if (this.isFullScreen) { const display = screen.getDisplayMatching(this.getBounds()); const defaultState = defaultWindowState(); @@ -907,7 +878,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } toggleFullScreen(): void { - this.setFullScreen(!this.isFullScreen()); + this.setFullScreen(!this.isFullScreen); } private setFullScreen(fullscreen: boolean): void { @@ -923,12 +894,12 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.sendWhenReady(fullscreen ? 'vscode:enterFullScreen' : 'vscode:leaveFullScreen'); // Respect configured menu bar visibility or default to toggle if not set - this.setMenuBarVisibility(this.currentMenuBarVisibility, false); + if (this.currentMenuBarVisibility) { + this.setMenuBarVisibility(this.currentMenuBarVisibility, false); + } } - isFullScreen(): boolean { - return this._win.isFullScreen() || this._win.isSimpleFullScreen(); - } + get isFullScreen(): boolean { return this._win.isFullScreen() || this._win.isSimpleFullScreen(); } private setNativeFullScreen(fullscreen: boolean): void { if (this._win.isSimpleFullScreen()) { @@ -1004,7 +975,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { } private doSetMenuBarVisibility(visibility: MenuBarVisibility): void { - const isFullscreen = this.isFullScreen(); + const isFullscreen = this.isFullScreen; switch (visibility) { case ('default'): diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts index fc6cbc48a85..17fcaf121bf 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts @@ -23,7 +23,7 @@ export class QuickOpenEditorWidget implements IOverlayWidget { private readonly codeEditor: ICodeEditor; private readonly themeService: IThemeService; - private visible: boolean; + private visible: boolean | undefined; private quickOpenWidget: QuickOpenWidget; private domNode: HTMLElement; private styler: IDisposable; @@ -55,29 +55,29 @@ export class QuickOpenEditorWidget implements IOverlayWidget { this.codeEditor.addOverlayWidget(this); } - public setInput(model: QuickOpenModel, focus: IAutoFocus): void { + setInput(model: QuickOpenModel, focus: IAutoFocus): void { this.quickOpenWidget.setInput(model, focus); } - public getId(): string { + getId(): string { return QuickOpenEditorWidget.ID; } - public getDomNode(): HTMLElement { + getDomNode(): HTMLElement { return this.domNode; } - public destroy(): void { + destroy(): void { this.codeEditor.removeOverlayWidget(this); this.quickOpenWidget.dispose(); this.styler.dispose(); } - public isVisible(): boolean { - return this.visible; + isVisible(): boolean { + return !!this.visible; } - public show(value: string): void { + show(value: string): void { this.visible = true; const editorLayout = this.codeEditor.getLayoutInfo(); @@ -89,13 +89,13 @@ export class QuickOpenEditorWidget implements IOverlayWidget { this.codeEditor.layoutOverlayWidget(this); } - public hide(): void { + hide(): void { this.visible = false; this.quickOpenWidget.hide(); this.codeEditor.layoutOverlayWidget(this); } - public getPosition(): IOverlayWidgetPosition | null { + getPosition(): IOverlayWidgetPosition | null { if (this.visible) { return { preference: OverlayWidgetPositionPreference.TOP_CENTER diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index 01d88e2ece8..17dfd5efde6 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -205,19 +205,20 @@ export class MenuEntryActionViewItem extends ActionViewItem { } updateLabel(): void { - if (this.options.label) { + if (this.options.label && this.label) { this.label.textContent = this._commandAction.label; } } updateTooltip(): void { - const element = this.label; - const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id); - const keybindingLabel = keybinding && keybinding.getLabel(); + if (this.label) { + const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id); + const keybindingLabel = keybinding && keybinding.getLabel(); - element.title = keybindingLabel - ? localize('titleAndKb', "{0} ({1})", this._commandAction.label, keybindingLabel) - : this._commandAction.label; + this.label.title = keybindingLabel + ? localize('titleAndKb', "{0} ({1})", this._commandAction.label, keybindingLabel) + : this._commandAction.label; + } } updateClass(): void { @@ -249,8 +250,14 @@ export class MenuEntryActionViewItem extends ActionViewItem { MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); } - addClasses(this.label, 'icon', iconClass); - this._itemClassDispose.value = toDisposable(() => removeClasses(this.label, 'icon', iconClass)); + if (this.label) { + addClasses(this.label, 'icon', iconClass); + this._itemClassDispose.value = toDisposable(() => { + if (this.label) { + removeClasses(this.label, 'icon', iconClass); + } + }); + } } } } diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index ab24a78884b..5635ece6180 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -213,14 +213,11 @@ export class BackupMainService implements IBackupMainService { } } - registerEmptyWindowBackupSync(backupFolder?: string, remoteAuthority?: string): string { + registerEmptyWindowBackupSync(backupFolderCandidate?: string, remoteAuthority?: string): string { // Generate a new folder if this is a new empty workspace - if (!backupFolder) { - backupFolder = this.getRandomEmptyWindowId(); - } - - if (!this.emptyWorkspaces.some(window => !!window.backupFolder && isEqual(window.backupFolder, backupFolder!, !platform.isLinux))) { + const backupFolder = backupFolderCandidate || this.getRandomEmptyWindowId(); + if (!this.emptyWorkspaces.some(window => !!window.backupFolder && isEqual(window.backupFolder, backupFolder, !platform.isLinux))) { this.emptyWorkspaces.push({ backupFolder, remoteAuthority }); this.saveSync(); } diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index bb666a1bc1b..eedee4a9f99 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -391,7 +391,7 @@ export class ElectronMainService implements IElectronMainService { const window = this.windowById(windowId); if (window) { const contents = window.win.webContents; - if (isMacintosh && window.hasHiddenTitleBarStyle() && !window.isFullScreen() && !contents.isDevToolsOpened()) { + if (isMacintosh && window.hasHiddenTitleBarStyle && !window.isFullScreen && !contents.isDevToolsOpened()) { contents.openDevTools({ mode: 'undocked' }); // due to https://github.com/electron/electron/issues/3647 } else { contents.toggleDevTools(); diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 026ed424e78..2e16afa9a53 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -234,7 +234,8 @@ export class LaunchMainService implements ILaunchMainService { const windows = this.windowsMainService.getWindows(); const promises: Promise[] = windows.map(window => { return new Promise((resolve, reject) => { - if (window.remoteAuthority) { + const remoteAuthority = window.remoteAuthority; + if (remoteAuthority) { const replyChannel = `vscode:getDiagnosticInfoResponse${window.id}`; const args: IDiagnosticInfoOptions = { includeProcesses: options.includeProcesses, @@ -246,14 +247,14 @@ export class LaunchMainService implements ILaunchMainService { ipcMain.once(replyChannel, (_: IpcEvent, data: IRemoteDiagnosticInfo) => { // No data is returned if getting the connection fails. if (!data) { - resolve({ hostName: window.remoteAuthority!, errorMessage: `Unable to resolve connection to '${window.remoteAuthority}'.` }); + resolve({ hostName: remoteAuthority, errorMessage: `Unable to resolve connection to '${remoteAuthority}'.` }); } resolve(data); }); setTimeout(() => { - resolve({ hostName: window.remoteAuthority!, errorMessage: `Fetching remote diagnostics for '${window.remoteAuthority}' timed out.` }); + resolve({ hostName: remoteAuthority, errorMessage: `Fetching remote diagnostics for '${remoteAuthority}' timed out.` }); }, 5000); } else { resolve(); diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 991f2cc4b99..a27b3dabca0 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -44,8 +44,8 @@ export class Menubar { private static readonly lastKnownMenubarStorageKey = 'lastKnownMenubarData'; - private willShutdown: boolean; - private appMenuInstalled: boolean; + private willShutdown: boolean | undefined; + private appMenuInstalled: boolean | undefined; private closedLastWindow: boolean; private menuUpdater: RunOnceScheduler; @@ -365,10 +365,11 @@ export class Menubar { const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' }); const quit = new MenuItem(this.likeAction('workbench.action.quit', { label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => { + const lastActiveWindow = this.windowsMainService.getLastActiveWindow(); if ( - this.windowsMainService.getWindowCount() === 0 || // allow to quit when no more windows are open - !!BrowserWindow.getFocusedWindow() || // allow to quit when window has focus (fix for https://github.com/Microsoft/vscode/issues/39191) - this.windowsMainService.getLastActiveWindow()!.isMinimized() // allow to quit when window has no focus but is minimized (https://github.com/Microsoft/vscode/issues/63000) + this.windowsMainService.getWindowCount() === 0 || // allow to quit when no more windows are open + !!BrowserWindow.getFocusedWindow() || // allow to quit when window has focus (fix for https://github.com/Microsoft/vscode/issues/39191) + (lastActiveWindow && lastActiveWindow.isMinimized()) // allow to quit when window has no focus but is minimized (https://github.com/Microsoft/vscode/issues/63000) ) { this.electronMainService.quit(undefined); } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 86d26e848ec..9d519473683 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -39,7 +39,7 @@ export interface ICodeWindow extends IDisposable { readonly id: number; readonly win: BrowserWindow; - readonly config: IWindowConfiguration; + readonly config: IWindowConfiguration | undefined; readonly openedFolderUri?: URI; readonly openedWorkspace?: IWorkspaceIdentifier; @@ -56,6 +56,8 @@ export interface ICodeWindow extends IDisposable { ready(): Promise; setReady(): void; + readonly hasHiddenTitleBarStyle: boolean; + addTabbedWindow(window: ICodeWindow): void; load(config: IWindowConfiguration, isReload?: boolean): void; @@ -69,14 +71,13 @@ export interface ICodeWindow extends IDisposable { send(channel: string, ...args: any[]): void; sendWhenReady(channel: string, ...args: any[]): void; + readonly isFullScreen: boolean; toggleFullScreen(): void; - isFullScreen(): boolean; + isMinimized(): boolean; - hasHiddenTitleBarStyle(): boolean; - setRepresentedFilename(name: string): void; - getRepresentedFilename(): string; + getRepresentedFilename(): string | undefined; handleTitleDoubleClick(): void; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 470f036424c..173db4ee066 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -459,7 +459,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // 1.) focus last active window if we are not instructed to open any paths if (focusLastActive) { - const lastActiveWindow = usedWindows.filter(window => window.backupPath === this.windowsState.lastActiveWindow!.backupPath); + const lastActiveWindow = usedWindows.filter(window => this.windowsState.lastActiveWindow && window.backupPath === this.windowsState.lastActiveWindow.backupPath); if (lastActiveWindow.length) { lastActiveWindow[0].focus(); focusLastOpened = false; @@ -472,9 +472,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic for (let i = usedWindows.length - 1; i >= 0; i--) { const usedWindow = usedWindows[i]; if ( - (usedWindow.openedWorkspace && workspacesToRestore.some(workspace => workspace.workspace.id === usedWindow.openedWorkspace!.id)) || // skip over restored workspace - (usedWindow.openedFolderUri && foldersToRestore.some(uri => isEqual(uri, usedWindow.openedFolderUri))) || // skip over restored folder - (usedWindow.backupPath && emptyToRestore.some(empty => empty.backupFolder === basename(usedWindow.backupPath!))) // skip over restored empty window + (usedWindow.openedWorkspace && workspacesToRestore.some(workspace => usedWindow.openedWorkspace && workspace.workspace.id === usedWindow.openedWorkspace.id)) || // skip over restored workspace + (usedWindow.openedFolderUri && foldersToRestore.some(uri => isEqual(uri, usedWindow.openedFolderUri))) || // skip over restored folder + (usedWindow.backupPath && emptyToRestore.some(empty => usedWindow.backupPath && empty.backupFolder === basename(usedWindow.backupPath))) // skip over restored empty window ) { continue; } @@ -559,7 +559,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const fileToCheck = fileInputs.filesToOpenOrCreate[0] || fileInputs.filesToDiff[0]; // only look at the windows with correct authority - const windows = WindowsMainService.WINDOWS.filter(window => window.remoteAuthority === fileInputs!.remoteAuthority); + const windows = WindowsMainService.WINDOWS.filter(window => fileInputs && window.remoteAuthority === fileInputs.remoteAuthority); const bestWindowOrFolder = findBestWindowOrFolderForFile({ windows, @@ -633,7 +633,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Open remaining ones allWorkspacesToOpen.forEach(workspaceToOpen => { - if (windowsOnWorkspace.some(win => win.openedWorkspace!.id === workspaceToOpen.workspace.id)) { + if (windowsOnWorkspace.some(win => win.openedWorkspace && win.openedWorkspace.id === workspaceToOpen.workspace.id)) { return; // ignore folders that are already open } @@ -1388,7 +1388,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic } // Create the window - window = this.instantiationService.createInstance(CodeWindow, { + const createdWindow = window = this.instantiationService.createInstance(CodeWindow, { state, extensionDevelopmentPath: configuration.extensionDevelopmentPath, isExtensionTestHost: !!configuration.extensionTestsPath @@ -1409,10 +1409,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length - 1, newCount: WindowsMainService.WINDOWS.length }); // Window Events - once(window.onClose)(() => this.onWindowClosed(window!)); - once(window.onDestroy)(() => this.onBeforeWindowClose(window!)); // try to save state before destroy because close will not fire + once(window.onClose)(() => this.onWindowClosed(createdWindow)); + once(window.onDestroy)(() => this.onBeforeWindowClose(createdWindow)); // try to save state before destroy because close will not fire window.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own - window.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(window!)); + window.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow)); // Lifecycle (this.lifecycleMainService as LifecycleMainService).registerWindow(window); diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index eb861920576..35017025a1c 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -265,6 +265,9 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain } const result = this.doEnterWorkspace(window, getWorkspaceIdentifier(path)); + if (!result) { + return null; + } // Emit as event this._onWorkspaceEntered.fire({ window, workspace: result.workspace }); @@ -300,7 +303,11 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain return true; // OK } - private doEnterWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult { + private doEnterWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult | null { + if (!window.config) { + return null; + } + window.focus(); // Register window for backups and migrate current backups over diff --git a/src/vs/platform/workspaces/electron-main/workspacesService.ts b/src/vs/platform/workspaces/electron-main/workspacesService.ts index 41f4cb982c2..24a9bfbcb18 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesService.ts @@ -52,7 +52,7 @@ export class WorkspacesService implements AddFirstParameterToFunctions { const window = this.windowsMainService.getWindowById(windowId); - if (window) { + if (window && window.config) { return this.workspacesHistoryMainService.getRecentlyOpened(window.config.workspace, window.config.folderUri, window.config.filesToOpenOrCreate); } diff --git a/src/vs/workbench/browser/actions.ts b/src/vs/workbench/browser/actions.ts index aac3da30445..6e9909e2633 100644 --- a/src/vs/workbench/browser/actions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -156,7 +156,7 @@ export interface IActionBarRegistry { class ActionBarRegistry implements IActionBarRegistry { private readonly actionBarContributorConstructors: { scope: string; ctor: IConstructorSignature0; }[] = []; private readonly actionBarContributorInstances: Map = new Map(); - private instantiationService!: IInstantiationService; + private instantiationService: IInstantiationService | undefined; start(accessor: ServicesAccessor): void { this.instantiationService = accessor.get(IInstantiationService); @@ -168,13 +168,15 @@ class ActionBarRegistry implements IActionBarRegistry { } private createActionBarContributor(scope: string, ctor: IConstructorSignature0): void { - const instance = this.instantiationService.createInstance(ctor); - let target = this.actionBarContributorInstances.get(scope); - if (!target) { - target = []; - this.actionBarContributorInstances.set(scope, target); + if (this.instantiationService) { + const instance = this.instantiationService.createInstance(ctor); + let target = this.actionBarContributorInstances.get(scope); + if (!target) { + target = []; + this.actionBarContributorInstances.set(scope, target); + } + target.push(instance); } - target.push(instance); } private getContributors(scope: string): ActionBarContributor[] { diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 190f5dcd853..05cd78e5a87 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -340,7 +340,7 @@ class ToggleTabsVisibilityAction extends Action { } registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTabsVisibilityAction, ToggleTabsVisibilityAction.ID, ToggleTabsVisibilityAction.LABEL, { - primary: undefined!, + primary: undefined, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, }, linux: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, } }), 'View: Toggle Tab Visibility', viewCategory); diff --git a/src/vs/workbench/browser/actions/navigationActions.ts b/src/vs/workbench/browser/actions/navigationActions.ts index 621f41f00f6..aa46d31242f 100644 --- a/src/vs/workbench/browser/actions/navigationActions.ts +++ b/src/vs/workbench/browser/actions/navigationActions.ts @@ -68,9 +68,19 @@ abstract class BaseNavigationAction extends Action { return false; } - const activePanelId = this.panelService.getActivePanel()!.getId(); + const activePanel = this.panelService.getActivePanel(); + if (!activePanel) { + return false; + } - return this.panelService.openPanel(activePanelId, true)!; + const activePanelId = activePanel.getId(); + + const res = this.panelService.openPanel(activePanelId, true); + if (!res) { + return false; + } + + return res; } protected async navigateToSidebar(): Promise { diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index 1c8f30a8f20..d29b5e51eaa 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -35,7 +35,7 @@ export abstract class Composite extends Component implements IComposite { private readonly _onDidChangeVisibility: Emitter = this._register(new Emitter()); readonly onDidChangeVisibility: Event = this._onDidChangeVisibility.event; - private _onDidFocus!: Emitter; + private _onDidFocus: Emitter; get onDidFocus(): Event { if (!this._onDidFocus) { this.registerFocusTrackEvents(); @@ -50,7 +50,7 @@ export abstract class Composite extends Component implements IComposite { } } - private _onDidBlur!: Emitter; + private _onDidBlur: Emitter; get onDidBlur(): Event { if (!this._onDidBlur) { this.registerFocusTrackEvents(); @@ -71,7 +71,7 @@ export abstract class Composite extends Component implements IComposite { protected actionRunner: IActionRunner | undefined; private visible: boolean; - private parent!: HTMLElement; + private parent: HTMLElement; constructor( id: string, diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 005a025aa9b..db31b88fadb 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -243,11 +243,13 @@ export class ResourcesDropHandler { } // Resolve the contents of the dropped dirty resource from source - try { - const content = await this.backupFileService.resolveBackupContent((droppedDirtyEditor.backupResource!)); - await this.backupFileService.backupResource(droppedDirtyEditor.resource, content.value.create(this.getDefaultEOL()).createSnapshot(true)); - } catch (e) { - // Ignore error + if (droppedDirtyEditor.backupResource) { + try { + const content = await this.backupFileService.resolveBackupContent((droppedDirtyEditor.backupResource)); + await this.backupFileService.backupResource(droppedDirtyEditor.resource, content.value.create(this.getDefaultEOL()).createSnapshot(true)); + } catch (e) { + // Ignore error + } } return false; diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index d9e9d143bed..899604797c2 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -434,7 +434,7 @@ class ResourceLabelWidget extends IconLabel { return; } - const iconLabelOptions: IIconLabelValueOptions = { + const iconLabelOptions: IIconLabelValueOptions & { extraClasses: string[] } = { title: '', italic: this.options && this.options.italic, matches: this.options && this.options.matches, @@ -462,7 +462,7 @@ class ResourceLabelWidget extends IconLabel { } if (this.options && this.options.extraClasses) { - iconLabelOptions.extraClasses!.push(...this.options.extraClasses); + iconLabelOptions.extraClasses.push(...this.options.extraClasses); } if (this.options && this.options.fileDecorations && resource) { @@ -477,11 +477,11 @@ class ResourceLabelWidget extends IconLabel { } if (this.options.fileDecorations.colors) { - iconLabelOptions.extraClasses!.push(deco.labelClassName); + iconLabelOptions.extraClasses.push(deco.labelClassName); } if (this.options.fileDecorations.badges) { - iconLabelOptions.extraClasses!.push(deco.badgeClassName); + iconLabelOptions.extraClasses.push(deco.badgeClassName); } } } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 883b7ca4cbe..7da6d53387a 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -1161,7 +1161,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi const width = this.storageService.getNumber(Storage.GRID_WIDTH, StorageScope.GLOBAL, workbenchDimensions.width); const height = this.storageService.getNumber(Storage.GRID_HEIGHT, StorageScope.GLOBAL, workbenchDimensions.height); // At some point, we will not fall back to old keys from legacy layout, but for now, let's migrate the keys - const sideBarSize = this.storageService.getNumber(Storage.SIDEBAR_SIZE, StorageScope.GLOBAL, this.storageService.getNumber('workbench.sidebar.width', StorageScope.GLOBAL, Math.min(workbenchDimensions.width / 4, 300))!); + const sideBarSize = this.storageService.getNumber(Storage.SIDEBAR_SIZE, StorageScope.GLOBAL, this.storageService.getNumber('workbench.sidebar.width', StorageScope.GLOBAL, Math.min(workbenchDimensions.width / 4, 300))); const panelSize = this.storageService.getNumber(Storage.PANEL_SIZE, StorageScope.GLOBAL, this.storageService.getNumber(this.state.panel.position === Position.BOTTOM ? 'workbench.panel.height' : 'workbench.panel.width', StorageScope.GLOBAL, workbenchDimensions.height / 3)); const titleBarHeight = this.titleBarPartView.minimumHeight; diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 7a39fce8178..b7a7d47044a 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -48,7 +48,7 @@ export class CompositeBar extends Widget implements ICompositeBar { private dimension: Dimension | undefined; - private compositeSwitcherBar!: ActionBar; + private compositeSwitcherBar: ActionBar; private compositeOverflowAction: CompositeOverflowActivityAction | undefined; private compositeOverflowActionViewItem: CompositeOverflowActivityActionViewItem | undefined; @@ -113,12 +113,15 @@ export class CompositeBar extends Widget implements ICompositeBar { if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { EventHelper.stop(e, true); - const draggedCompositeId = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype)![0].id; - this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data)) { + const draggedCompositeId = data[0].id; + this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); - const targetItem = this.model.visibleItems[this.model.visibleItems.length - 1]; - if (targetItem && targetItem.id !== draggedCompositeId) { - this.move(draggedCompositeId, targetItem.id); + const targetItem = this.model.visibleItems[this.model.visibleItems.length - 1]; + if (targetItem && targetItem.id !== draggedCompositeId) { + this.move(draggedCompositeId, targetItem.id); + } } } })); diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index dde3549cd8f..7485e7a8658 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -57,7 +57,7 @@ export class ActivityAction extends Action { private readonly _onDidChangeBadge = new Emitter(); readonly onDidChangeBadge: Event = this._onDidChangeBadge.event; - private badge?: IBadge; + private badge: IBadge | undefined; private clazz: string | undefined; constructor(private _activity: IActivity) { @@ -124,10 +124,10 @@ export interface IActivityActionViewItemOptions extends IBaseActionViewItemOptio } export class ActivityActionViewItem extends BaseActionViewItem { - protected container!: HTMLElement; - protected label!: HTMLElement; - protected badge!: HTMLElement; - protected options!: IActivityActionViewItemOptions; + protected container: HTMLElement; + protected label: HTMLElement; + protected badge: HTMLElement; + protected options: IActivityActionViewItemOptions; private badgeContent: HTMLElement | undefined; private readonly badgeDisposable = this._register(new MutableDisposable()); @@ -205,10 +205,10 @@ export class ActivityActionViewItem extends BaseActionViewItem { })); // Label - this.label = dom.append(this.element!, dom.$('a')); + this.label = dom.append(container, dom.$('a')); // Badge - this.badge = dom.append(this.element!, dom.$('.badge')); + this.badge = dom.append(container, dom.$('.badge')); this.badgeContent = dom.append(this.badge, dom.$('.badge-content')); dom.hide(this.badge); @@ -347,7 +347,7 @@ export class CompositeOverflowActivityAction extends ActivityAction { } export class CompositeOverflowActivityActionViewItem extends ActivityActionViewItem { - private actions: Action[] | undefined; + private actions: Action[] = []; constructor( action: ActivityAction, @@ -370,9 +370,9 @@ export class CompositeOverflowActivityActionViewItem extends ActivityActionViewI this.actions = this.getActions(); this.contextMenuService.showContextMenu({ - getAnchor: () => this.element!, - getActions: () => this.actions!, - onHide: () => dispose(this.actions!) + getAnchor: () => this.container, + getActions: () => this.actions, + onHide: () => dispose(this.actions) }); } @@ -502,7 +502,9 @@ export class CompositeActionViewItem extends ActivityActionViewItem { // Allow to drag this._register(dom.addDisposableListener(this.container, dom.EventType.DRAG_START, (e: DragEvent) => { - e.dataTransfer!.effectAllowed = 'move'; + if (e.dataTransfer) { + e.dataTransfer.effectAllowed = 'move'; + } // Registe as dragged to local transfer this.compositeTransfer.setData([new DraggedCompositeIdentifier(this.activity.id)], DraggedCompositeIdentifier.prototype); @@ -515,8 +517,11 @@ export class CompositeActionViewItem extends ActivityActionViewItem { this._register(new DragAndDropObserver(this.container, { onDragEnter: e => { - if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) && this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype)![0].id !== this.activity.id) { - this.updateFromDragging(container, true); + if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data) && data[0].id !== this.activity.id) { + this.updateFromDragging(container, true); + } } }, @@ -538,12 +543,15 @@ export class CompositeActionViewItem extends ActivityActionViewItem { dom.EventHelper.stop(e, true); if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { - const draggedCompositeId = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype)![0].id; - if (draggedCompositeId !== this.activity.id) { - this.updateFromDragging(container, false); - this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data)) { + const draggedCompositeId = data[0].id; + if (draggedCompositeId !== this.activity.id) { + this.updateFromDragging(container, false); + this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); - this.compositeBar.move(draggedCompositeId, this.activity.id); + this.compositeBar.move(draggedCompositeId, this.activity.id); + } } } } diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 9531cb8a75b..1058b69e765 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -57,15 +57,15 @@ export abstract class CompositePart extends Part { protected readonly onDidCompositeOpen = this._register(new Emitter<{ composite: IComposite, focus: boolean }>()); protected readonly onDidCompositeClose = this._register(new Emitter()); - protected toolBar!: ToolBar; + protected toolBar: ToolBar; private mapCompositeToCompositeContainer = new Map(); private mapActionsBindingToComposite = new Map void>(); private activeComposite: Composite | null; private lastActiveCompositeId: string; private instantiatedCompositeItems: Map; - private titleLabel!: ICompositeTitleLabel; - private progressBar!: ProgressBar; + private titleLabel: ICompositeTitleLabel; + private progressBar: ProgressBar; private contentAreaSize: Dimension | undefined; private readonly telemetryActionsListener = this._register(new MutableDisposable()); private currentCompositeOpenToken: string | undefined; diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 0aa5e53d0eb..167933b3db1 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -495,7 +495,7 @@ export class CloseOneEditorAction extends Action { group = this.editorGroupService.getGroup(context.groupId); if (group) { - editorIndex = context.editorIndex!; // only allow editor at index if group is valid + editorIndex = context.editorIndex; // only allow editor at index if group is valid } } diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 2113a4e7c50..da2fa254db3 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -108,7 +108,16 @@ class DropOverlay extends Themable { } // Find out if operation is valid - const isCopy = isDraggingGroup ? this.isCopyOperation(e) : isDraggingEditor ? this.isCopyOperation(e, this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier) : true; + let isCopy = true; + if (isDraggingGroup) { + isCopy = this.isCopyOperation(e); + } else if (isDraggingEditor) { + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + isCopy = this.isCopyOperation(e, data[0].identifier); + } + } + if (!isCopy) { const sourceGroupView = this.findSourceGroupView(); if (sourceGroupView === this.groupView) { @@ -162,12 +171,18 @@ class DropOverlay extends Themable { // Check for group transfer if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - return this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier); + const data = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype); + if (Array.isArray(data)) { + return this.accessor.getGroup(data[0].identifier); + } } // Check for editor transfer else if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier.groupId); + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + return this.accessor.getGroup(data[0].identifier.groupId); + } } return undefined; @@ -189,69 +204,75 @@ class DropOverlay extends Themable { // Check for group transfer if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const draggedEditorGroup = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier; + const data = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype); + if (Array.isArray(data)) { + const draggedEditorGroup = data[0].identifier; - // Return if the drop is a no-op - const sourceGroup = this.accessor.getGroup(draggedEditorGroup); - if (sourceGroup) { - if (typeof splitDirection !== 'number' && sourceGroup === this.groupView) { - return; - } + // Return if the drop is a no-op + const sourceGroup = this.accessor.getGroup(draggedEditorGroup); + if (sourceGroup) { + if (typeof splitDirection !== 'number' && sourceGroup === this.groupView) { + return; + } - // Split to new group - let targetGroup: IEditorGroupView | undefined; - if (typeof splitDirection === 'number') { - if (this.isCopyOperation(event)) { - targetGroup = this.accessor.copyGroup(sourceGroup, this.groupView, splitDirection); - } else { - targetGroup = this.accessor.moveGroup(sourceGroup, this.groupView, splitDirection); + // Split to new group + let targetGroup: IEditorGroupView | undefined; + if (typeof splitDirection === 'number') { + if (this.isCopyOperation(event)) { + targetGroup = this.accessor.copyGroup(sourceGroup, this.groupView, splitDirection); + } else { + targetGroup = this.accessor.moveGroup(sourceGroup, this.groupView, splitDirection); + } + } + + // Merge into existing group + else { + if (this.isCopyOperation(event)) { + targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView, { mode: MergeGroupMode.COPY_EDITORS }); + } else { + targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView); + } + } + + if (targetGroup) { + this.accessor.activateGroup(targetGroup); } } - // Merge into existing group - else { - if (this.isCopyOperation(event)) { - targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView, { mode: MergeGroupMode.COPY_EDITORS }); - } else { - targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView); - } - } - - if (targetGroup) { - this.accessor.activateGroup(targetGroup); - } + this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype); } - - this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype); } // Check for editor transfer else if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; - const targetGroup = ensureTargetGroup(); + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + const draggedEditor = data[0].identifier; + const targetGroup = ensureTargetGroup(); - // Return if the drop is a no-op - const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); - if (sourceGroup) { - if (sourceGroup === targetGroup) { - return; + // Return if the drop is a no-op + const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); + if (sourceGroup) { + if (sourceGroup === targetGroup) { + return; + } + + // Open in target group + const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true })); + targetGroup.openEditor(draggedEditor.editor, options); + + // Ensure target has focus + targetGroup.focus(); + + // Close in source group unless we copy + const copyEditor = this.isCopyOperation(event, draggedEditor); + if (!copyEditor) { + sourceGroup.closeEditor(draggedEditor.editor); + } } - // Open in target group - const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true })); - targetGroup.openEditor(draggedEditor.editor, options); - - // Ensure target has focus - targetGroup.focus(); - - // Close in source group unless we copy - const copyEditor = this.isCopyOperation(event, draggedEditor); - if (!copyEditor) { - sourceGroup.closeEditor(draggedEditor.editor); - } + this.editorTransfer.clearData(DraggedEditorIdentifier.prototype); } - - this.editorTransfer.clearData(DraggedEditorIdentifier.prototype); } // Check for URI transfer diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 647abff323a..2f2e982262e 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -730,20 +730,24 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { const textModel = editorWidget.getModel(); if (textModel) { info.selections.forEach(selection => { - info.charactersSelected! += textModel.getValueLengthInRange(selection); + if (typeof info.charactersSelected !== 'number') { + info.charactersSelected = 0; + } + + info.charactersSelected += textModel.getValueLengthInRange(selection); }); } // Compute the visible column for one selection. This will properly handle tabs and their configured widths if (info.selections.length === 1) { - const visibleColumn = editorWidget.getVisibleColumnFromPosition(editorWidget.getPosition()!); + const editorPosition = editorWidget.getPosition(); let selectionClone = info.selections[0].clone(); // do not modify the original position we got from the editor selectionClone = new Selection( selectionClone.selectionStartLineNumber, selectionClone.selectionStartColumn, selectionClone.positionLineNumber, - visibleColumn + editorPosition ? editorWidget.getVisibleColumnFromPosition(editorPosition) : selectionClone.positionColumn ); info.selections[0] = selectionClone; diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 691ae0570ac..b993b3a5b05 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -44,7 +44,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; interface IEditorInputLabel { - name: string; + name?: string; description?: string; title?: string; } @@ -206,7 +206,10 @@ export class TabsTitleControl extends TitleControl { // Return if transfer is unsupported if (!this.isSupportedDropTransfer(e)) { - e.dataTransfer!.dropEffect = 'none'; + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + } + return; } @@ -215,17 +218,25 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; - if (this.group.id === localDraggedEditor.groupId && this.group.getIndexOfEditor(localDraggedEditor.editor) === this.group.count - 1) { - e.dataTransfer!.dropEffect = 'none'; - return; + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + const localDraggedEditor = data[0].identifier; + if (this.group.id === localDraggedEditor.groupId && this.group.getIndexOfEditor(localDraggedEditor.editor) === this.group.count - 1) { + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + } + + return; + } } } // Update the dropEffect to "copy" if there is no local data to be dragged because // in that case we can only copy the data into and not move it from its source if (!isLocalDragAndDrop) { - e.dataTransfer!.dropEffect = 'copy'; + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'copy'; + } } this.updateDropFeedback(this.tabsContainer, true); @@ -602,7 +613,9 @@ export class TabsTitleControl extends TitleControl { this.editorTransfer.setData([new DraggedEditorIdentifier({ editor, groupId: this.group.id })], DraggedEditorIdentifier.prototype); - e.dataTransfer!.effectAllowed = 'copyMove'; + if (e.dataTransfer) { + e.dataTransfer.effectAllowed = 'copyMove'; + } // Apply some datatransfer types to allow for dragging the element outside of the application const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER }); @@ -624,7 +637,10 @@ export class TabsTitleControl extends TitleControl { // Return if transfer is unsupported if (!this.isSupportedDropTransfer(e)) { - e.dataTransfer!.dropEffect = 'none'; + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + } + return; } @@ -633,17 +649,25 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; - if (localDraggedEditor.editor === this.group.getEditor(index) && localDraggedEditor.groupId === this.group.id) { - e.dataTransfer!.dropEffect = 'none'; - return; + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + const localDraggedEditor = data[0].identifier; + if (localDraggedEditor.editor === this.group.getEditor(index) && localDraggedEditor.groupId === this.group.id) { + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + } + + return; + } } } // Update the dropEffect to "copy" if there is no local data to be dragged because // in that case we can only copy the data into and not move it from its source if (!isLocalDragAndDrop) { - e.dataTransfer!.dropEffect = 'copy'; + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'copy'; + } } this.updateDropFeedback(tab, true, index); @@ -674,9 +698,12 @@ export class TabsTitleControl extends TitleControl { private isSupportedDropTransfer(e: DragEvent): boolean { if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0]; - if (group.identifier === this.group.id) { - return false; // groups cannot be dropped on title area it originates from + const data = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype); + if (Array.isArray(data)) { + const group = data[0]; + if (group.identifier === this.group.id) { + return false; // groups cannot be dropped on title area it originates from + } } return true; @@ -724,7 +751,7 @@ export class TabsTitleControl extends TitleControl { // Build labels and descriptions for each editor const labels = this.group.editors.map(editor => ({ editor, - name: editor.getName()!, + name: editor.getName(), description: editor.getDescription(verbosity), title: withNullAsUndefined(editor.getTitle(Verbosity.LONG)) })); @@ -1018,8 +1045,8 @@ export class TabsTitleControl extends TitleControl { const visibleContainerWidth = this.tabsContainer.offsetWidth; const totalContainerWidth = this.tabsContainer.scrollWidth; - let activeTabPosX: number; - let activeTabWidth: number; + let activeTabPosX: number | undefined; + let activeTabWidth: number | undefined; if (!this.blockRevealActiveTab) { activeTabPosX = activeTab.offsetLeft; @@ -1033,27 +1060,27 @@ export class TabsTitleControl extends TitleControl { }); // Return now if we are blocked to reveal the active tab and clear flag - if (this.blockRevealActiveTab) { + if (this.blockRevealActiveTab || typeof activeTabPosX !== 'number' || typeof activeTabWidth !== 'number') { this.blockRevealActiveTab = false; return; } // Reveal the active one const containerScrollPosX = this.tabsScrollbar.getScrollPosition().scrollLeft; - const activeTabFits = activeTabWidth! <= visibleContainerWidth; + const activeTabFits = activeTabWidth <= visibleContainerWidth; // Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right // Note: only try to do this if we actually have enough width to give to show the tab fully! - if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX! + activeTabWidth!) { + if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) { this.tabsScrollbar.setScrollPosition({ - scrollLeft: containerScrollPosX + ((activeTabPosX! + activeTabWidth!) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */) + scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */) }); } // Tab is overlflowng to the left or does not fit: Scroll it into view to the left - else if (containerScrollPosX > activeTabPosX! || !activeTabFits) { + else if (containerScrollPosX > activeTabPosX || !activeTabFits) { this.tabsScrollbar.setScrollPosition({ - scrollLeft: activeTabPosX! + scrollLeft: activeTabPosX }); } } @@ -1096,41 +1123,47 @@ export class TabsTitleControl extends TitleControl { // Local Editor DND if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; - const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); + const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype); + if (Array.isArray(data)) { + const draggedEditor = data[0].identifier; + const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); - if (sourceGroup) { + if (sourceGroup) { - // Move editor to target position and index - if (this.isMoveOperation(e, draggedEditor.groupId)) { - sourceGroup.moveEditor(draggedEditor.editor, this.group, { index: targetIndex }); + // Move editor to target position and index + if (this.isMoveOperation(e, draggedEditor.groupId)) { + sourceGroup.moveEditor(draggedEditor.editor, this.group, { index: targetIndex }); + } + + // Copy editor to target position and index + else { + sourceGroup.copyEditor(draggedEditor.editor, this.group, { index: targetIndex }); + } } - // Copy editor to target position and index - else { - sourceGroup.copyEditor(draggedEditor.editor, this.group, { index: targetIndex }); - } + this.group.focus(); + this.editorTransfer.clearData(DraggedEditorIdentifier.prototype); } - - this.group.focus(); - this.editorTransfer.clearData(DraggedEditorIdentifier.prototype); } // Local Editor Group DND else if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier); + const data = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype); + if (data) { + const sourceGroup = this.accessor.getGroup(data[0].identifier); - if (sourceGroup) { - const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex }; - if (!this.isMoveOperation(e, sourceGroup.id)) { - mergeGroupOptions.mode = MergeGroupMode.COPY_EDITORS; + if (sourceGroup) { + const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex }; + if (!this.isMoveOperation(e, sourceGroup.id)) { + mergeGroupOptions.mode = MergeGroupMode.COPY_EDITORS; + } + + this.accessor.mergeGroup(sourceGroup, this.group, mergeGroupOptions); } - this.accessor.mergeGroup(sourceGroup, this.group, mergeGroupOptions); + this.group.focus(); + this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype); } - - this.group.focus(); - this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype); } // External DND diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index fd36123986e..0f6d34e29aa 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -133,7 +133,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { // Editor for Text this._editorContainer = parent; - this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue(this.getResource()!)))); + this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue(this.getResource())))); // Model & Language changes const codeEditor = getCodeEditor(this.editorControl); diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 089bbbc8875..d84d340acb8 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -257,7 +257,9 @@ export abstract class TitleControl extends Themable { // Set editor group as transfer this.groupTransfer.setData([new DraggedEditorGroupIdentifier(this.group.id)], DraggedEditorGroupIdentifier.prototype); - e.dataTransfer!.effectAllowed = 'copyMove'; + if (e.dataTransfer) { + e.dataTransfer.effectAllowed = 'copyMove'; + } // If tabs are disabled, treat dragging as if an editor tab was dragged if (!this.accessor.partOptions.showTabs) { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index 3c13be13ad2..a2599e246ec 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -91,7 +91,7 @@ export class NotificationsList extends Themable { } this.contextMenuService.showContextMenu({ - getAnchor: () => e.anchor!, + getAnchor: () => e.anchor, getActions: () => [copyAction], getActionsContext: () => e.element, actionRunner diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 103e0075498..05f24184cfb 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -303,9 +303,9 @@ export class PanelPart extends CompositePart implements IPanelService { } if (this.layoutService.getPanelPosition() === Position.RIGHT) { - this._contentDimension = new Dimension(width - 1, height!); // Take into account the 1px border when layouting + this._contentDimension = new Dimension(width - 1, height); // Take into account the 1px border when layouting } else { - this._contentDimension = new Dimension(width, height!); + this._contentDimension = new Dimension(width, height); } // Layout contents diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index c3b76e31974..f4b35007b80 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -225,8 +225,17 @@ export class SidebarPart extends CompositePart implements IViewletServi } getViewlets(): ViewletDescriptor[] { - return this.viewletRegistry.getViewlets() - .sort((v1, v2) => v1.order! - v2.order!); + return this.viewletRegistry.getViewlets().sort((v1, v2) => { + if (typeof v1.order !== 'number') { + return -1; + } + + if (typeof v2.order !== 'number') { + return 1; + } + + return v1.order - v2.order; + }); } getDefaultViewletId(): string { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 769c08aef05..065c4fec998 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -238,7 +238,10 @@ class StatusbarViewModel extends Disposable { return entryB.priority - entryA.priority; // higher priority towards the left } - return mapEntryToIndex.get(entryA)! - mapEntryToIndex.get(entryB)!; // otherwise maintain stable order + const indexA = mapEntryToIndex.get(entryA); + const indexB = mapEntryToIndex.get(entryB); + + return indexA! - indexB!; // otherwise maintain stable order (both values known to be in map) } if (entryA.alignment === StatusbarAlignment.LEFT) { @@ -334,14 +337,14 @@ export class StatusbarPart extends Part implements IStatusbarService { //#endregion - private styleElement!: HTMLStyleElement; + private styleElement: HTMLStyleElement; private pendingEntries: IPendingStatusbarEntry[] = []; private readonly viewModel: StatusbarViewModel; - private leftItemsContainer!: HTMLElement; - private rightItemsContainer!: HTMLElement; + private leftItemsContainer: HTMLElement; + private rightItemsContainer: HTMLElement; constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -691,8 +694,9 @@ class StatusbarEntryItem extends Disposable { if (!this.entry || entry.command !== this.entry.command) { this.commandListener.clear(); - if (entry.command) { - this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(entry.command!, entry.arguments)); + const command = entry.command; + if (command) { + this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command, entry.arguments)); removeClass(this.labelContainer, 'disabled'); } else { diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 112067306da..bd676c25d02 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -570,10 +570,10 @@ export class CustomMenubarControl extends MenubarControl { for (let action of actions) { this.insertActionsBefore(action, target); if (action instanceof SubmenuItemAction) { - if (!this.menus[action.item.submenu]) { - this.menus[action.item.submenu] = this.menuService.createMenu(action.item.submenu, this.contextKeyService); - const submenu = this.menus[action.item.submenu]; - this._register(submenu!.onDidChange(() => { + let submenu = this.menus[action.item.submenu]; + if (!submenu) { + submenu = this.menus[action.item.submenu] = this.menuService.createMenu(action.item.submenu, this.contextKeyService); + this._register(submenu.onDidChange(() => { if (!this.focusInsideMenubar) { const actions: IAction[] = []; updateActions(menu, actions, topLevelTitle); @@ -582,7 +582,6 @@ export class CustomMenubarControl extends MenubarControl { }, this)); } - const submenu = this.menus[action.item.submenu]!; const submenuActions: SubmenuAction[] = []; updateActions(submenu, submenuActions, topLevelTitle); target.push(new SubmenuAction(mnemonicMenuLabel(action.label), submenuActions)); diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index c690b885a6c..1fc235927cb 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -18,7 +18,7 @@ import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; import * as nls from 'vs/nls'; import { EditorInput, toResource, Verbosity, SideBySideEditor } from 'vs/workbench/common/editor'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } 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 { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform'; @@ -288,7 +288,15 @@ export class TitlebarPart extends Part implements ITitleService { // Compute folder resource // Single Root Workspace: always the root single workspace in this case // Otherwise: root folder of the currently active file if any - const folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor, { supportSideBySide: SideBySideEditor.MASTER })!); + let folder: IWorkspaceFolder | null = null; + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + folder = workspace.folders[0]; + } else { + const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER }); + if (resource) { + folder = this.contextService.getWorkspaceFolder(resource); + } + } // Variables const activeEditorShort = editor ? editor.getTitle(Verbosity.SHORT) : ''; diff --git a/src/vs/workbench/common/contributions.ts b/src/vs/workbench/common/contributions.ts index 0d89c00ae0e..e2a4ca4d321 100644 --- a/src/vs/workbench/common/contributions.ts +++ b/src/vs/workbench/common/contributions.ts @@ -63,11 +63,11 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry } start(accessor: ServicesAccessor): void { - this.instantiationService = accessor.get(IInstantiationService); - this.lifecycleService = accessor.get(ILifecycleService); + const instantiationService = this.instantiationService = accessor.get(IInstantiationService); + const lifecycleService = this.lifecycleService = accessor.get(ILifecycleService); [LifecyclePhase.Starting, LifecyclePhase.Ready, LifecyclePhase.Restored, LifecyclePhase.Eventually].forEach(phase => { - this.instantiateByPhase(this.instantiationService!, this.lifecycleService!, phase); + this.instantiateByPhase(instantiationService, lifecycleService, phase); }); } diff --git a/src/vs/workbench/common/editor/binaryEditorModel.ts b/src/vs/workbench/common/editor/binaryEditorModel.ts index dc631e33a88..319f0a2c080 100644 --- a/src/vs/workbench/common/editor/binaryEditorModel.ts +++ b/src/vs/workbench/common/editor/binaryEditorModel.ts @@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; import { DataUri, basename } from 'vs/base/common/resources'; +import { MIME_BINARY } from 'vs/base/common/mime'; /** * An editor model that just represents a resource that can be loaded. @@ -33,7 +34,7 @@ export class BinaryEditorModel extends EditorModel { this.size = Number(metadata.get(DataUri.META_DATA_SIZE)); } - this.mime = metadata.get(DataUri.META_DATA_MIME)!; + this.mime = metadata.get(DataUri.META_DATA_MIME) || MIME_BINARY; } } diff --git a/src/vs/workbench/common/editor/textDiffEditorModel.ts b/src/vs/workbench/common/editor/textDiffEditorModel.ts index f18c71fe3c8..dc2f7405b98 100644 --- a/src/vs/workbench/common/editor/textDiffEditorModel.ts +++ b/src/vs/workbench/common/editor/textDiffEditorModel.ts @@ -14,8 +14,8 @@ import { DiffEditorModel } from 'vs/workbench/common/editor/diffEditorModel'; */ export class TextDiffEditorModel extends DiffEditorModel { - protected readonly _originalModel!: BaseTextEditorModel | null; - protected readonly _modifiedModel!: BaseTextEditorModel | null; + protected readonly _originalModel: BaseTextEditorModel | null; + protected readonly _modifiedModel: BaseTextEditorModel | null; private _textDiffEditorModel: IDiffEditorModel | null = null; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 53de865d8f1..f4f4ce7df80 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -180,24 +180,24 @@ export class ResourceGlobMatcher extends Disposable { matches(resource: URI): boolean { const folder = this.contextService.getWorkspaceFolder(resource); - let expressionForRoot: ParsedExpression; + let expressionForRoot: ParsedExpression | undefined; if (folder && this.mapRootToParsedExpression.has(folder.uri.toString())) { - expressionForRoot = this.mapRootToParsedExpression.get(folder.uri.toString())!; + expressionForRoot = this.mapRootToParsedExpression.get(folder.uri.toString()); } else { - expressionForRoot = this.mapRootToParsedExpression.get(ResourceGlobMatcher.NO_ROOT)!; + expressionForRoot = this.mapRootToParsedExpression.get(ResourceGlobMatcher.NO_ROOT); } // If the resource if from a workspace, convert its absolute path to a relative // path so that glob patterns have a higher probability to match. For example // a glob pattern of "src/**" will not match on an absolute path "/folder/src/file.txt" // but can match on "src/file.txt" - let resourcePathToMatch: string; + let resourcePathToMatch: string | undefined; if (folder) { - resourcePathToMatch = relativePath(folder.uri, resource)!; // always uses forward slashes + resourcePathToMatch = relativePath(folder.uri, resource); // always uses forward slashes } else { resourcePathToMatch = resource.fsPath; // TODO@isidor: support non-file URIs } - return !!expressionForRoot(resourcePathToMatch); + return !!expressionForRoot && typeof resourcePathToMatch === 'string' && !!expressionForRoot(resourcePathToMatch); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts index a06e6ce4017..a5ae07ec17f 100644 --- a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts +++ b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts @@ -33,6 +33,10 @@ export class ReactionActionViewItem extends ActionViewItem { super(null, action, {}); } updateLabel(): void { + if (!this.label) { + return; + } + let action = this.getAction() as ReactionAction; if (action.class) { this.label.classList.add(action.class); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index d8be403fe9e..94982ae98bb 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -566,7 +566,7 @@ export class ExtensionActionViewItem extends ActionViewItem { updateEnabled(): void { super.updateEnabled(); - if (this.options.tabOnlyOnFocus && this.getAction().enabled && !this._hasFocus) { + if (this.label && this.options.tabOnlyOnFocus && this.getAction().enabled && !this._hasFocus) { DOM.removeTabIndexAndUpdateFocus(this.label); } } @@ -577,7 +577,7 @@ export class ExtensionActionViewItem extends ActionViewItem { return; } this._hasFocus = value; - if (this.getAction().enabled) { + if (this.label && this.getAction().enabled) { if (this._hasFocus) { this.label.tabIndex = 0; } else { diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index c6954daaa0c..60c0027a6df 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -114,7 +114,9 @@ export class EmptyView extends ViewletPanel { container.style.backgroundColor = color ? color.toString() : ''; }, onDragOver: e => { - e.dataTransfer!.dropEffect = 'copy'; + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'copy'; + } } })); diff --git a/src/vs/workbench/contrib/scm/browser/mainPanel.ts b/src/vs/workbench/contrib/scm/browser/mainPanel.ts index 134f70ce0ba..4718b319830 100644 --- a/src/vs/workbench/contrib/scm/browser/mainPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/mainPanel.ts @@ -82,7 +82,7 @@ class StatusBarActionViewItem extends ActionViewItem { } updateLabel(): void { - if (this.options.label) { + if (this.options.label && this.label) { this.label.innerHTML = renderOcticons(this.getAction().label); } } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 3647d409cb7..42bf33c1191 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -632,8 +632,8 @@ export class ElectronWindow extends Disposable { await this.lifecycleService.when(LifecyclePhase.Ready); // In diffMode we open 2 resources as diff - if (diffMode && resources.length === 2) { - return this.editorService.openEditor({ leftResource: resources[0].resource!, rightResource: resources[1].resource!, options: { pinned: true } }); + if (diffMode && resources.length === 2 && resources[0].resource && resources[1].resource) { + return this.editorService.openEditor({ leftResource: resources[0].resource, rightResource: resources[1].resource, options: { pinned: true } }); } // For one file, just put it into the current active editor @@ -742,8 +742,8 @@ class NativeMenubarControl extends MenubarControl { const submenu = { items: [] }; if (!this.menus[menuItem.item.submenu]) { - this.menus[menuItem.item.submenu] = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService); - this._register(this.menus[menuItem.item.submenu]!.onDidChange(() => this.updateMenubar())); + const menu = this.menus[menuItem.item.submenu] = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService); + this._register(menu.onDidChange(() => this.updateMenubar())); } const menuToDispose = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService); diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 62c657356da..f8f7325be35 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -848,7 +848,7 @@ export class SimpleFileDialog { } private createBackItem(currFolder: URI): FileQuickPickItem | null { - const parentFolder = resources.dirname(currFolder)!; + const parentFolder = resources.dirname(currFolder); if (!resources.isEqual(currFolder, parentFolder, true)) { return { label: '..', uri: resources.addTrailingPathSeparator(parentFolder, this.separator), isFolder: true }; } diff --git a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts index e317751fd39..a3df05aa176 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts @@ -149,7 +149,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil const defaultUri = options.defaultUri; - const newOptions: OpenDialogOptions = { + const newOptions: OpenDialogOptions & { properties: string[] } = { title: options.title, defaultPath: defaultUri && defaultUri.fsPath, buttonLabel: options.openLabel, @@ -157,18 +157,18 @@ export class FileDialogService extends AbstractFileDialogService implements IFil properties: [] }; - newOptions.properties!.push('createDirectory'); + newOptions.properties.push('createDirectory'); if (options.canSelectFiles) { - newOptions.properties!.push('openFile'); + newOptions.properties.push('openFile'); } if (options.canSelectFolders) { - newOptions.properties!.push('openDirectory'); + newOptions.properties.push('openDirectory'); } if (options.canSelectMany) { - newOptions.properties!.push('multiSelections'); + newOptions.properties.push('multiSelections'); } const result = await this.electronService.showOpenDialog(newOptions); diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 9eb8d8c8a9e..99b5ff364d3 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -152,8 +152,9 @@ export class EditorService extends Disposable implements EditorServiceImpl { for (const handler of this.openEditorHandlers) { const result = handler(event.editor, event.options, group); - if (result && result.override) { - event.prevent((() => result.override!.then(editor => withNullAsUndefined(editor)))); + const override = result ? result.override : undefined; + if (override) { + event.prevent((() => override.then(editor => withNullAsUndefined(editor)))); break; } } diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index de6fad7d5fd..6cccb046251 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -120,7 +120,7 @@ export class HistoryService extends Disposable implements IHistoryService { private lastEditLocation: IStackEntry | undefined; - private history!: Array; + private history: Array; private recentlyClosedFiles: IRecentlyClosedFile[]; private loaded: boolean; private resourceFilter: ResourceGlobMatcher; @@ -250,7 +250,11 @@ export class HistoryService extends Disposable implements IHistoryService { // Track the last edit location by tracking model content change events // Use a debouncer to make sure to capture the correct cursor position // after the model content has changed. - this.activeEditorListeners.add(Event.debounce(activeTextEditorWidget.onDidChangeModelContent, (last, event) => event, 0)((event => this.rememberLastEditLocation(activeEditor!, activeTextEditorWidget)))); + this.activeEditorListeners.add(Event.debounce(activeTextEditorWidget.onDidChangeModelContent, (last, event) => event, 0)((event => { + if (activeEditor) { + this.rememberLastEditLocation(activeEditor, activeTextEditorWidget); + } + }))); } } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts index 7a87bbb0bd6..e459f336e17 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts @@ -38,7 +38,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE private readonly _onModelOrphanedChanged: Emitter = this._register(new Emitter()); readonly onModelOrphanedChanged: Event = this._onModelOrphanedChanged.event; - private _onModelsDirty!: Event; + private _onModelsDirty: Event | undefined; get onModelsDirty(): Event { if (!this._onModelsDirty) { this._onModelsDirty = this.debounce(this.onModelDirty); @@ -47,7 +47,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE return this._onModelsDirty; } - private _onModelsSaveError!: Event; + private _onModelsSaveError: Event | undefined; get onModelsSaveError(): Event { if (!this._onModelsSaveError) { this._onModelsSaveError = this.debounce(this.onModelSaveError); @@ -56,7 +56,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE return this._onModelsSaveError; } - private _onModelsSaved!: Event; + private _onModelsSaved: Event | undefined; get onModelsSaved(): Event { if (!this._onModelsSaved) { this._onModelsSaved = this.debounce(this.onModelSaved); @@ -65,7 +65,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE return this._onModelsSaved; } - private _onModelsReverted!: Event; + private _onModelsReverted: Event | undefined; get onModelsReverted(): Event { if (!this._onModelsReverted) { this._onModelsReverted = this.debounce(this.onModelReverted); diff --git a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts index 6c7b6033307..a7e977a09a2 100644 --- a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts @@ -67,7 +67,7 @@ export class NativeTextFileService extends AbstractTextFileService { super(contextService, fileService, untitledEditorService, lifecycleService, instantiationService, configurationService, modeService, modelService, environmentService, notificationService, backupFileService, historyService, contextKeyService, dialogService, fileDialogService, editorService, textResourceConfigurationService); } - private _encoding!: EncodingOracle; + private _encoding: EncodingOracle | undefined; get encoding(): EncodingOracle { if (!this._encoding) { this._encoding = this._register(this.instantiationService.createInstance(EncodingOracle)); From 66eea492f8328a53b0f857f86efac7c56b480352 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 10:42:20 +0200 Subject: [PATCH 202/435] debt - introduce and use assertDefined for strict init (#78168) --- src/vs/base/common/types.ts | 33 ++++++++++ src/vs/base/test/common/types.test.ts | 18 ++++++ src/vs/workbench/browser/panel.ts | 5 +- .../browser/parts/editor/binaryEditor.ts | 27 ++++++--- .../browser/parts/editor/editorWidgets.ts | 6 +- .../parts/editor/noTabsTitleControl.ts | 60 ++++++++++--------- .../browser/parts/editor/resourceViewer.ts | 10 ++-- .../browser/parts/editor/sideBySideEditor.ts | 28 +++++---- .../browser/parts/editor/textDiffEditor.ts | 28 +++++---- .../browser/parts/editor/textEditor.ts | 47 ++++++++------- .../parts/editor/textResourceEditor.ts | 28 +++++---- .../browser/parts/editor/titleControl.ts | 11 ++-- .../notifications/notificationsCenter.ts | 51 +++++++++------- .../parts/notifications/notificationsList.ts | 48 ++++++++------- .../notifications/notificationsToasts.ts | 35 ++++++----- .../browser/parts/statusbar/statusbarPart.ts | 11 ++-- src/vs/workbench/browser/quickopen.ts | 32 +++++----- src/vs/workbench/browser/viewlet.ts | 5 +- src/vs/workbench/common/editor.ts | 36 +++++------ .../common/editor/binaryEditorModel.ts | 10 +++- .../common/editor/diffEditorModel.ts | 3 +- .../common/editor/textDiffEditorModel.ts | 3 + .../files/browser/editors/textFileEditor.ts | 12 ++-- .../preferences/browser/preferencesEditor.ts | 13 ++-- .../contrib/quickopen/browser/helpHandler.ts | 10 ++-- .../contrib/search/browser/replaceService.ts | 2 +- .../host/browser/browserHostService.ts | 22 ++++--- .../workbench/test/workbenchTestServices.ts | 44 +++++++------- 28 files changed, 381 insertions(+), 257 deletions(-) diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 2ce9e0eb47c..f464f9a0cb4 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -93,6 +93,39 @@ export function isUndefinedOrNull(obj: any): obj is undefined | null { return isUndefined(obj) || obj === null; } +/** + * Asserts that the argument passed in is neither undefined nor null. + */ +export function assertIsDefined(arg: T | null | undefined): T { + if (isUndefinedOrNull(arg)) { + throw new Error('Assertion Failed: argument is undefined or null'); + } + + return arg; +} + +/** + * Asserts that each argument passed in is neither undefined nor null. + */ +export function assertAllDefined(t1: T1 | null | undefined, t2: T2 | null | undefined): [T1, T2]; +export function assertAllDefined(t1: T1 | null | undefined, t2: T2 | null | undefined, t3: T3 | null | undefined): [T1, T2, T3]; +export function assertAllDefined(t1: T1 | null | undefined, t2: T2 | null | undefined, t3: T3 | null | undefined, t4: T4 | null | undefined): [T1, T2, T3, T4]; +export function assertAllDefined(...args: (unknown | null | undefined)[]): unknown[] { + const result = []; + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + + if (isUndefinedOrNull(arg)) { + throw new Error(`Assertion Failed: argument at index ${i} is undefined or null`); + } + + result.push(arg); + } + + return result; +} + const hasOwnProperty = Object.prototype.hasOwnProperty; /** diff --git a/src/vs/base/test/common/types.test.ts b/src/vs/base/test/common/types.test.ts index 43241b9a9c2..90e174dd000 100644 --- a/src/vs/base/test/common/types.test.ts +++ b/src/vs/base/test/common/types.test.ts @@ -169,6 +169,24 @@ suite('Types', () => { assert(types.isUndefinedOrNull(null)); }); + test('assertIsDefined / assertAreDefined', () => { + assert.throws(() => types.assertIsDefined(undefined)); + assert.throws(() => types.assertIsDefined(null)); + assert.throws(() => types.assertAllDefined(null, undefined)); + assert.throws(() => types.assertAllDefined(true, undefined)); + assert.throws(() => types.assertAllDefined(undefined, false)); + + assert.equal(types.assertIsDefined(true), true); + assert.equal(types.assertIsDefined(false), false); + assert.equal(types.assertIsDefined('Hello'), 'Hello'); + assert.equal(types.assertIsDefined(''), ''); + + const res = types.assertAllDefined(1, true, 'Hello'); + assert.equal(res[0], 1); + assert.equal(res[1], true); + assert.equal(res[2], 'Hello'); + }); + test('validateConstraints', () => { types.validateConstraints([1, 'test', true], [Number, String, Boolean]); types.validateConstraints([1, 'test', true], ['number', 'string', 'boolean']); diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index 3e1a33fbe2c..a3f613dead4 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -11,6 +11,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; import { isAncestor } from 'vs/base/browser/dom'; +import { assertIsDefined } from 'vs/base/common/types'; export abstract class Panel extends Composite implements IPanel { } @@ -25,7 +26,7 @@ export class PanelDescriptor extends CompositeDescriptor { } export class PanelRegistry extends CompositeRegistry { - private defaultPanelId!: string; + private defaultPanelId: string | undefined; /** * Registers a panel to the platform. @@ -66,7 +67,7 @@ export class PanelRegistry extends CompositeRegistry { * Gets the id of the panel that should open on startup by default. */ getDefaultPanelId(): string { - return this.defaultPanelId; + return assertIsDefined(this.defaultPanelId); } /** diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index 380573ef808..53b00a24b33 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -19,6 +19,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { dispose } from 'vs/base/common/lifecycle'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; export interface IOpenCallbacks { openInternal: (input: EditorInput, options: EditorOptions | undefined) => Promise; @@ -38,8 +39,8 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { private callbacks: IOpenCallbacks; private metadata: string | undefined; - private binaryContainer: HTMLElement; - private scrollbar: DomScrollableElement; + private binaryContainer: HTMLElement | undefined; + private scrollbar: DomScrollableElement | undefined; private resourceViewerContext: ResourceViewerContext | undefined; constructor( @@ -91,7 +92,8 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { this.resourceViewerContext.dispose(); } - this.resourceViewerContext = ResourceViewer.show({ name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag(), mime: model.getMime() }, this.binaryContainer, this.scrollbar, { + const [binaryContainer, scrollbar] = assertAllDefined(this.binaryContainer, this.scrollbar); + this.resourceViewerContext = ResourceViewer.show({ name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag(), mime: model.getMime() }, binaryContainer, scrollbar, { openInternalClb: () => this.handleOpenInternalCallback(input, options), openExternalClb: this.environmentService.configuration.remoteAuthority ? undefined : resource => this.callbacks.openExternal(resource), metadataClb: meta => this.handleMetadataChanged(meta) @@ -120,8 +122,10 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { // Clear Meta this.handleMetadataChanged(undefined); - // Clear Resource Viewer - clearNode(this.binaryContainer); + // Clear the rest + if (this.binaryContainer) { + clearNode(this.binaryContainer); + } dispose(this.resourceViewerContext); this.resourceViewerContext = undefined; @@ -131,19 +135,24 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { layout(dimension: Dimension): void { // Pass on to Binary Container - size(this.binaryContainer, dimension.width, dimension.height); - this.scrollbar.scanDomNode(); + const [binaryContainer, scrollbar] = assertAllDefined(this.binaryContainer, this.scrollbar); + size(binaryContainer, dimension.width, dimension.height); + scrollbar.scanDomNode(); if (this.resourceViewerContext && this.resourceViewerContext.layout) { this.resourceViewerContext.layout(dimension); } } focus(): void { - this.binaryContainer.focus(); + const binaryContainer = assertIsDefined(this.binaryContainer); + + binaryContainer.focus(); } dispose(): void { - this.binaryContainer.remove(); + if (this.binaryContainer) { + this.binaryContainer.remove(); + } dispose(this.resourceViewerContext); this.resourceViewerContext = undefined; diff --git a/src/vs/workbench/browser/parts/editor/editorWidgets.ts b/src/vs/workbench/browser/parts/editor/editorWidgets.ts index 1a311045ad9..6616272abb1 100644 --- a/src/vs/workbench/browser/parts/editor/editorWidgets.ts +++ b/src/vs/workbench/browser/parts/editor/editorWidgets.ts @@ -8,7 +8,7 @@ import { IOverlayWidget, ICodeEditor, IOverlayWidgetPosition, OverlayWidgetPosit import { Event, Emitter } from 'vs/base/common/event'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { $, append } from 'vs/base/browser/dom'; +import { $, append, clearNode } from 'vs/base/browser/dom'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { buttonBackground, buttonForeground, editorBackground, editorForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -37,6 +37,8 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { ) { super(); + this._domNode = $('.floating-click-widget'); + if (keyBindingAction) { const keybinding = keybindingService.lookupKeybinding(keyBindingAction); if (keybinding) { @@ -60,7 +62,7 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { } render() { - this._domNode = $('.floating-click-widget'); + clearNode(this._domNode); this._register(attachStylerCallback(this.themeService, { buttonBackground, buttonForeground, editorBackground, editorForeground, contrastBorder }, colors => { const backgroundColor = colors.buttonBackground ? colors.buttonBackground : colors.editorBackground; diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index ff9fde91e90..b170188ae15 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -14,7 +14,7 @@ import { EDITOR_TITLE_HEIGHT } from 'vs/workbench/browser/parts/editor/editor'; import { IAction } from 'vs/base/common/actions'; import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { Color } from 'vs/base/common/color'; -import { withNullAsUndefined } from 'vs/base/common/types'; +import { withNullAsUndefined, assertIsDefined, assertAllDefined } from 'vs/base/common/types'; interface IRenderedEditorLabel { editor?: IEditorInput; @@ -22,23 +22,23 @@ interface IRenderedEditorLabel { } export class NoTabsTitleControl extends TitleControl { - private titleContainer: HTMLElement; - private editorLabel: IResourceLabel; + private titleContainer: HTMLElement | undefined; + private editorLabel: IResourceLabel | undefined; private activeLabel: IRenderedEditorLabel = Object.create(null); protected create(parent: HTMLElement): void { - this.titleContainer = parent; - this.titleContainer.draggable = true; + const titleContainer = this.titleContainer = parent; + titleContainer.draggable = true; //Container listeners - this.registerContainerListeners(); + this.registerContainerListeners(titleContainer); // Gesture Support - this._register(Gesture.addTarget(this.titleContainer)); + this._register(Gesture.addTarget(titleContainer)); const labelContainer = document.createElement('div'); addClass(labelContainer, 'label-container'); - this.titleContainer.appendChild(labelContainer); + titleContainer.appendChild(labelContainer); // Editor Label this.editorLabel = this._register(this.instantiationService.createInstance(ResourceLabel, labelContainer, undefined)).element; @@ -46,41 +46,41 @@ export class NoTabsTitleControl extends TitleControl { // Breadcrumbs this.createBreadcrumbsControl(labelContainer, { showFileIcons: false, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: () => Color.transparent }); - toggleClass(this.titleContainer, 'breadcrumbs', Boolean(this.breadcrumbsControl)); - this._register({ dispose: () => removeClass(this.titleContainer, 'breadcrumbs') }); // import to remove because the container is a shared dom node + toggleClass(titleContainer, 'breadcrumbs', Boolean(this.breadcrumbsControl)); + this._register({ dispose: () => removeClass(titleContainer, 'breadcrumbs') }); // import to remove because the container is a shared dom node // Right Actions Container const actionsContainer = document.createElement('div'); addClass(actionsContainer, 'title-actions'); - this.titleContainer.appendChild(actionsContainer); + titleContainer.appendChild(actionsContainer); // Editor actions toolbar this.createEditorActionsToolBar(actionsContainer); } - private registerContainerListeners(): void { + private registerContainerListeners(titleContainer: HTMLElement): void { // Group dragging - this.enableGroupDragging(this.titleContainer); + this.enableGroupDragging(titleContainer); // Pin on double click - this._register(addDisposableListener(this.titleContainer, EventType.DBLCLICK, (e: MouseEvent) => this.onTitleDoubleClick(e))); + this._register(addDisposableListener(titleContainer, EventType.DBLCLICK, (e: MouseEvent) => this.onTitleDoubleClick(e))); // Detect mouse click - this._register(addDisposableListener(this.titleContainer, EventType.MOUSE_UP, (e: MouseEvent) => this.onTitleClick(e))); + this._register(addDisposableListener(titleContainer, EventType.MOUSE_UP, (e: MouseEvent) => this.onTitleClick(e))); // Detect touch - this._register(addDisposableListener(this.titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e))); + this._register(addDisposableListener(titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e))); // Context Menu - this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => { + this._register(addDisposableListener(titleContainer, EventType.CONTEXT_MENU, (e: Event) => { if (this.group.activeEditor) { - this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + this.onContextMenu(this.group.activeEditor, e, titleContainer); } })); - this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => { + this._register(addDisposableListener(titleContainer, TouchEventType.Contextmenu, (e: Event) => { if (this.group.activeEditor) { - this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + this.onContextMenu(this.group.activeEditor, e, titleContainer); } })); } @@ -157,10 +157,11 @@ export class NoTabsTitleControl extends TitleControl { updateEditorDirty(editor: IEditorInput): void { this.ifEditorIsActive(editor, () => { + const titleContainer = assertIsDefined(this.titleContainer); if (editor.isDirty()) { - addClass(this.titleContainer, 'dirty'); + addClass(titleContainer, 'dirty'); } else { - removeClass(this.titleContainer, 'dirty'); + removeClass(titleContainer, 'dirty'); } }); } @@ -176,7 +177,9 @@ export class NoTabsTitleControl extends TitleControl { } protected handleBreadcrumbsEnablementChange(): void { - toggleClass(this.titleContainer, 'breadcrumbs', Boolean(this.breadcrumbsControl)); + const titleContainer = assertIsDefined(this.titleContainer); + + toggleClass(titleContainer, 'breadcrumbs', Boolean(this.breadcrumbsControl)); this.redraw(); } @@ -230,9 +233,10 @@ export class NoTabsTitleControl extends TitleControl { } // Clear if there is no editor + const [titleContainer, editorLabel] = assertAllDefined(this.titleContainer, this.editorLabel); if (!editor) { - removeClass(this.titleContainer, 'dirty'); - this.editorLabel.clear(); + removeClass(titleContainer, 'dirty'); + editorLabel.clear(); this.clearEditorActionsToolbar(); } @@ -261,11 +265,11 @@ export class NoTabsTitleControl extends TitleControl { title = ''; // dont repeat what is already shown } - this.editorLabel.setResource({ name, description, resource: resource || undefined }, { title: typeof title === 'string' ? title : undefined, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] }); + editorLabel.setResource({ name, description, resource: resource || undefined }, { title: typeof title === 'string' ? title : undefined, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] }); if (isGroupActive) { - this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND); + editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND); } else { - this.editorLabel.element.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND); + editorLabel.element.style.color = this.getColor(TAB_UNFOCUSED_ACTIVE_FOREGROUND); } // Update Editor Actions Toolbar diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts index 773755ec961..c87b88479de 100644 --- a/src/vs/workbench/browser/parts/editor/resourceViewer.ts +++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts @@ -16,7 +16,7 @@ import { IMAGE_PREVIEW_BORDER } from 'vs/workbench/common/theme'; export interface IResourceDescriptor { readonly resource: URI; readonly name: string; - readonly size: number; + readonly size?: number; readonly etag?: string; readonly mime: string; } @@ -82,8 +82,8 @@ export class ResourceViewer { container.className = 'monaco-resource-viewer'; // Large Files - if (descriptor.size > ResourceViewer.MAX_OPEN_INTERNAL_SIZE) { - return FileTooLargeFileView.create(container, descriptor, scrollbar, delegate); + if (typeof descriptor.size === 'number' && descriptor.size > ResourceViewer.MAX_OPEN_INTERNAL_SIZE) { + return FileTooLargeFileView.create(container, descriptor.size, scrollbar, delegate); } // Seemingly Binary Files @@ -96,11 +96,11 @@ export class ResourceViewer { class FileTooLargeFileView { static create( container: HTMLElement, - descriptor: IResourceDescriptor, + descriptorSize: number, scrollbar: DomScrollableElement, delegate: ResourceViewerDelegate ) { - const size = BinarySize.formatSize(descriptor.size); + const size = BinarySize.formatSize(descriptorSize); delegate.metadataClb(size); DOM.clearNode(container); diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index b05cb17d70f..9d8ae67d35b 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -17,6 +17,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { Event, Relay, Emitter } from 'vs/base/common/event'; import { IStorageService } from 'vs/platform/storage/common/storage'; +import { assertIsDefined } from 'vs/base/common/types'; export class SideBySideEditor extends BaseEditor { @@ -47,10 +48,10 @@ export class SideBySideEditor extends BaseEditor { protected masterEditor?: BaseEditor; protected detailsEditor?: BaseEditor; - private masterEditorContainer: HTMLElement; - private detailsEditorContainer: HTMLElement; + private masterEditorContainer: HTMLElement | undefined; + private detailsEditorContainer: HTMLElement | undefined; - private splitview: SplitView; + private splitview: SplitView | undefined; private dimension: DOM.Dimension = new DOM.Dimension(0, 0); private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; } | undefined>()); @@ -69,8 +70,8 @@ export class SideBySideEditor extends BaseEditor { protected createEditor(parent: HTMLElement): void { DOM.addClass(parent, 'side-by-side-editor'); - this.splitview = this._register(new SplitView(parent, { orientation: Orientation.HORIZONTAL })); - this._register(this.splitview.onDidSashReset(() => this.splitview.distributeViewSizes())); + const splitview = this.splitview = this._register(new SplitView(parent, { orientation: Orientation.HORIZONTAL })); + this._register(this.splitview.onDidSashReset(() => splitview.distributeViewSizes())); this.detailsEditorContainer = DOM.$('.details-editor-container'); this.splitview.addView({ @@ -140,7 +141,9 @@ export class SideBySideEditor extends BaseEditor { layout(dimension: DOM.Dimension): void { this.dimension = dimension; - this.splitview.layout(dimension.width); + + const splitview = assertIsDefined(this.splitview); + splitview.layout(dimension.width); } getControl(): IEditorControl | undefined { @@ -179,8 +182,8 @@ export class SideBySideEditor extends BaseEditor { } private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise { - const detailsEditor = this.doCreateEditor(newInput.details, this.detailsEditorContainer); - const masterEditor = this.doCreateEditor(newInput.master, this.masterEditorContainer); + const detailsEditor = this.doCreateEditor(newInput.details, assertIsDefined(this.detailsEditorContainer)); + const masterEditor = this.doCreateEditor(newInput.master, assertIsDefined(this.masterEditorContainer)); return this.onEditorsCreated(detailsEditor, masterEditor, newInput.details, newInput.master, options, token); } @@ -234,8 +237,13 @@ export class SideBySideEditor extends BaseEditor { this.masterEditor = undefined; } - this.detailsEditorContainer.innerHTML = ''; - this.masterEditorContainer.innerHTML = ''; + if (this.detailsEditorContainer) { + DOM.clearNode(this.detailsEditorContainer); + } + + if (this.masterEditorContainer) { + DOM.clearNode(this.masterEditorContainer); + } } dispose(): void { diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index cec875895b5..e4d132cc598 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import * as objects from 'vs/base/common/objects'; -import { isFunction, isObject, isArray } from 'vs/base/common/types'; +import { isFunction, isObject, isArray, assertIsDefined } from 'vs/base/common/types'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -100,7 +100,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { } // Set Editor Model - const diffEditor = this.getControl(); + const diffEditor = assertIsDefined(this.getControl()); const resolvedDiffEditorModel = resolvedModel; diffEditor.setModel(resolvedDiffEditorModel.textDiffEditorModel); @@ -113,7 +113,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { // Otherwise restore View State let hasPreviousViewState = false; if (!optionsGotApplied) { - hasPreviousViewState = this.restoreTextDiffEditorViewState(input); + hasPreviousViewState = this.restoreTextDiffEditorViewState(input, diffEditor); } // Diff navigator @@ -138,17 +138,18 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { setOptions(options: EditorOptions | undefined): void { const textOptions = options; if (textOptions && isFunction(textOptions.apply)) { - textOptions.apply(this.getControl(), ScrollType.Smooth); + const diffEditor = assertIsDefined(this.getControl()); + textOptions.apply(diffEditor, ScrollType.Smooth); } } - private restoreTextDiffEditorViewState(input: EditorInput): boolean { - if (input instanceof DiffEditorInput) { - const resource = this.toDiffEditorViewStateResource(input); + private restoreTextDiffEditorViewState(editor: EditorInput, control: IDiffEditor): boolean { + if (editor instanceof DiffEditorInput) { + const resource = this.toDiffEditorViewStateResource(editor); if (resource) { const viewState = this.loadTextEditorViewState(resource); if (viewState) { - this.getControl().restoreViewState(viewState); + control.restoreViewState(viewState); return true; } @@ -258,7 +259,10 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { this.saveTextDiffEditorViewState(this.input); // Clear Model - this.getControl().setModel(null); + const diffEditor = this.getControl(); + if (diffEditor) { + diffEditor.setModel(null); + } // Pass to super super.clearInput(); @@ -268,8 +272,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { return this.diffNavigator; } - getControl(): IDiffEditor { - return super.getControl() as IDiffEditor; + getControl(): IDiffEditor | undefined { + return super.getControl() as IDiffEditor | undefined; } protected loadTextEditorViewState(resource: URI): IDiffEditorViewState { @@ -307,7 +311,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { } private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState | null { - const control = this.getControl(); + const control = assertIsDefined(this.getControl()); const model = control.getModel(); if (!model || !model.modified || !model.original) { return null; // view state always needs a model diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index 0f6d34e29aa..ab5403342c3 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import * as objects from 'vs/base/common/objects'; -import * as types from 'vs/base/common/types'; -import * as DOM from 'vs/base/browser/dom'; +import { distinct, deepClone, assign } from 'vs/base/common/objects'; +import { isObject, assertIsDefined } from 'vs/base/common/types'; +import { Dimension } from 'vs/base/browser/dom'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { EditorInput, EditorOptions, IEditorMemento, ITextEditor } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; @@ -37,8 +37,8 @@ export interface IEditorConfiguration { * be subclassed and not instantiated. */ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { - private editorControl: IEditor; - private _editorContainer: HTMLElement; + private editorControl: IEditor | undefined; + private _editorContainer: HTMLElement | undefined; private hasPendingConfigurationChange: boolean | undefined; private lastAppliedEditorOptions?: IEditorOptions; private editorMemento: IEditorMemento; @@ -96,8 +96,8 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { protected computeConfiguration(configuration: IEditorConfiguration): IEditorOptions { // Specific editor options always overwrite user configuration - const editorConfiguration: IEditorOptions = types.isObject(configuration.editor) ? objects.deepClone(configuration.editor) : Object.create(null); - objects.assign(editorConfiguration, this.getConfigurationOverrides()); + const editorConfiguration: IEditorOptions = isObject(configuration.editor) ? deepClone(configuration.editor) : Object.create(null); + assign(editorConfiguration, this.getConfigurationOverrides()); // ARIA label editorConfiguration.ariaLabel = this.computeAriaLabel(); @@ -111,7 +111,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { // Apply group information to help identify in which group we are if (ariaLabel) { if (this.group) { - ariaLabel = nls.localize('editorLabelWithGroup', "{0}, {1}.", ariaLabel, this.group.label); + ariaLabel = localize('editorLabelWithGroup', "{0}, {1}.", ariaLabel, this.group.label); } } @@ -120,7 +120,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { protected getConfigurationOverrides(): IEditorOptions { const overrides = {}; - objects.assign(overrides, { + assign(overrides, { overviewRulerLanes: 3, lineNumbersMinChars: 3, fixedOverflowWidgets: true @@ -197,33 +197,40 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { // Update editor options after having set the input. We do this because there can be // editor input specific options (e.g. an ARIA label depending on the input showing) this.updateEditorConfiguration(); - this._editorContainer.setAttribute('aria-label', this.computeAriaLabel()); + + const editorContainer = assertIsDefined(this._editorContainer); + editorContainer.setAttribute('aria-label', this.computeAriaLabel()); } protected setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void { // Pass on to Editor + const editorControl = assertIsDefined(this.editorControl); if (visible) { this.consumePendingConfigurationChangeEvent(); - this.editorControl.onVisible(); + editorControl.onVisible(); } else { - this.editorControl.onHide(); + editorControl.onHide(); } super.setEditorVisible(visible, group); } focus(): void { - this.editorControl.focus(); - } - - layout(dimension: DOM.Dimension): void { // Pass on to Editor - this.editorControl.layout(dimension); + const editorControl = assertIsDefined(this.editorControl); + editorControl.focus(); } - getControl(): IEditor { + layout(dimension: Dimension): void { + + // Pass on to Editor + const editorControl = assertIsDefined(this.editorControl); + editorControl.layout(dimension); + } + + getControl(): IEditor | undefined { return this.editorControl; } @@ -296,7 +303,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor { // have been applied to the editor directly. let editorSettingsToApply = editorConfiguration; if (this.lastAppliedEditorOptions) { - editorSettingsToApply = objects.distinct(this.lastAppliedEditorOptions, editorSettingsToApply); + editorSettingsToApply = distinct(this.lastAppliedEditorOptions, editorSettingsToApply); } if (Object.keys(editorSettingsToApply).length > 0) { diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index d7e9666628f..866bb82c0f2 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as types from 'vs/base/common/types'; +import { assertIsDefined, isFunction } from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { TextEditorOptions, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; @@ -19,7 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { Event } from 'vs/base/common/event'; -import { ScrollType } from 'vs/editor/common/editorCommon'; +import { ScrollType, IEditor } from 'vs/editor/common/editorCommon'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -74,36 +74,37 @@ export class AbstractTextResourceEditor extends BaseTextEditor { } // Set Editor Model - const textEditor = this.getControl(); + const textEditor = assertIsDefined(this.getControl()); const textEditorModel = resolvedModel.textEditorModel; textEditor.setModel(textEditorModel); // Apply Options from TextOptions let optionsGotApplied = false; const textOptions = options; - if (textOptions && types.isFunction(textOptions.apply)) { + if (textOptions && isFunction(textOptions.apply)) { optionsGotApplied = textOptions.apply(textEditor, ScrollType.Immediate); } // Otherwise restore View State if (!optionsGotApplied) { - this.restoreTextResourceEditorViewState(input); + this.restoreTextResourceEditorViewState(input, textEditor); } } - private restoreTextResourceEditorViewState(input: EditorInput) { - if (input instanceof UntitledEditorInput || input instanceof ResourceEditorInput) { - const viewState = this.loadTextEditorViewState(input.getResource()); + private restoreTextResourceEditorViewState(editor: EditorInput, control: IEditor) { + if (editor instanceof UntitledEditorInput || editor instanceof ResourceEditorInput) { + const viewState = this.loadTextEditorViewState(editor.getResource()); if (viewState) { - this.getControl().restoreViewState(viewState); + control.restoreViewState(viewState); } } } setOptions(options: EditorOptions | undefined): void { const textOptions = options; - if (textOptions && types.isFunction(textOptions.apply)) { - textOptions.apply(this.getControl(), ScrollType.Smooth); + if (textOptions && isFunction(textOptions.apply)) { + const textEditor = assertIsDefined(this.getControl()); + textOptions.apply(textEditor, ScrollType.Smooth); } } @@ -149,7 +150,10 @@ export class AbstractTextResourceEditor extends BaseTextEditor { this.saveTextResourceEditorViewState(this.input); // Clear Model - this.getControl().setModel(null); + const textEditor = this.getControl(); + if (textEditor) { + textEditor.setModel(null); + } super.clearInput(); } diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index d84d340acb8..30b2652363e 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -39,7 +39,7 @@ import { Themable } from 'vs/workbench/common/theme'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { IFileService } from 'vs/platform/files/common/files'; -import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; +import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; export interface IToolbarActions { @@ -57,7 +57,7 @@ export abstract class TitleControl extends Themable { private currentPrimaryEditorActionIds: string[] = []; private currentSecondaryEditorActionIds: string[] = []; - private editorActionsToolbar: ToolBar; + private editorActionsToolbar: ToolBar | undefined; private resourceContext: ResourceContextKey; private editorPinnedContext: IContextKey; @@ -188,7 +188,8 @@ export abstract class TitleControl extends Themable { primaryEditorActions.some(action => action instanceof ExecuteCommandAction) || // execute command actions can have the same ID but different arguments secondaryEditorActions.some(action => action instanceof ExecuteCommandAction) // see also https://github.com/Microsoft/vscode/issues/16298 ) { - this.editorActionsToolbar.setActions(primaryEditorActions, secondaryEditorActions)(); + const editorActionsToolbar = assertIsDefined(this.editorActionsToolbar); + editorActionsToolbar.setActions(primaryEditorActions, secondaryEditorActions)(); this.currentPrimaryEditorActionIds = primaryEditorActionIds; this.currentSecondaryEditorActionIds = secondaryEditorActionIds; @@ -241,7 +242,9 @@ export abstract class TitleControl extends Themable { } protected clearEditorActionsToolbar(): void { - this.editorActionsToolbar.setActions([], [])(); + if (this.editorActionsToolbar) { + this.editorActionsToolbar.setActions([], [])(); + } this.currentPrimaryEditorActionIds = []; this.currentSecondaryEditorActionIds = []; diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index a0077787b11..77a4a66b55c 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -22,6 +22,7 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { ClearAllNotificationsAction, HideNotificationsCenterAction, NotificationActionRunner } from 'vs/workbench/browser/parts/notifications/notificationsActions'; import { IAction } from 'vs/base/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { assertAllDefined, assertIsDefined } from 'vs/base/common/types'; export class NotificationsCenter extends Themable { @@ -30,12 +31,12 @@ export class NotificationsCenter extends Themable { private readonly _onDidChangeVisibility: Emitter = this._register(new Emitter()); readonly onDidChangeVisibility: Event = this._onDidChangeVisibility.event; - private notificationsCenterContainer: HTMLElement; - private notificationsCenterHeader: HTMLElement; - private notificationsCenterTitle: HTMLSpanElement; - private notificationsList: NotificationsList; - private _isVisible: boolean; - private workbenchDimensions: Dimension; + private notificationsCenterContainer: HTMLElement | undefined; + private notificationsCenterHeader: HTMLElement | undefined; + private notificationsCenterTitle: HTMLSpanElement | undefined; + private notificationsList: NotificationsList | undefined; + private _isVisible: boolean | undefined; + private workbenchDimensions: Dimension | undefined; private notificationsCenterVisibleContextKey: IContextKey; constructor( @@ -61,12 +62,13 @@ export class NotificationsCenter extends Themable { } get isVisible(): boolean { - return this._isVisible; + return !!this._isVisible; } show(): void { if (this._isVisible) { - this.notificationsList.show(true /* focus */); + const notificationsList = assertIsDefined(this.notificationsList); + notificationsList.show(true /* focus */); return; // already visible } @@ -80,18 +82,19 @@ export class NotificationsCenter extends Themable { this.updateTitle(); // Make visible + const [notificationsList, notificationsCenterContainer] = assertAllDefined(this.notificationsList, this.notificationsCenterContainer); this._isVisible = true; - addClass(this.notificationsCenterContainer, 'visible'); - this.notificationsList.show(); + addClass(notificationsCenterContainer, 'visible'); + notificationsList.show(); // Layout this.layout(this.workbenchDimensions); // Show all notifications that are present now - this.notificationsList.updateNotificationsList(0, 0, this.model.notifications); + notificationsList.updateNotificationsList(0, 0, this.model.notifications); // Focus first - this.notificationsList.focusFirst(); + notificationsList.focusFirst(); // Theming this.updateStyles(); @@ -104,10 +107,12 @@ export class NotificationsCenter extends Themable { } private updateTitle(): void { + const notificationsCenterTitle = assertIsDefined(this.notificationsCenterTitle); + if (this.model.notifications.length === 0) { - this.notificationsCenterTitle.textContent = localize('notificationsEmpty', "No new notifications"); + notificationsCenterTitle.textContent = localize('notificationsEmpty', "No new notifications"); } else { - this.notificationsCenterTitle.textContent = localize('notifications', "Notifications"); + notificationsCenterTitle.textContent = localize('notifications', "Notifications"); } } @@ -167,16 +172,17 @@ export class NotificationsCenter extends Themable { let focusGroup = false; // Update notifications list based on event + const [notificationsList, notificationsCenterContainer] = assertAllDefined(this.notificationsList, this.notificationsCenterContainer); switch (e.kind) { case NotificationChangeType.ADD: - this.notificationsList.updateNotificationsList(e.index, 0, [e.item]); + notificationsList.updateNotificationsList(e.index, 0, [e.item]); break; case NotificationChangeType.CHANGE: - this.notificationsList.updateNotificationsList(e.index, 1, [e.item]); + notificationsList.updateNotificationsList(e.index, 1, [e.item]); break; case NotificationChangeType.REMOVE: - focusGroup = isAncestor(document.activeElement, this.notificationsCenterContainer); - this.notificationsList.updateNotificationsList(e.index, 1); + focusGroup = isAncestor(document.activeElement, notificationsCenterContainer); + notificationsList.updateNotificationsList(e.index, 1); break; } @@ -195,7 +201,7 @@ export class NotificationsCenter extends Themable { } hide(): void { - if (!this._isVisible || !this.notificationsCenterContainer) { + if (!this._isVisible || !this.notificationsCenterContainer || !this.notificationsList) { return; // already hidden } @@ -219,7 +225,7 @@ export class NotificationsCenter extends Themable { } protected updateStyles(): void { - if (this.notificationsCenterContainer) { + if (this.notificationsCenterContainer && this.notificationsCenterHeader) { const widgetShadowColor = this.getColor(widgetShadow); this.notificationsCenterContainer.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : null; @@ -234,7 +240,7 @@ export class NotificationsCenter extends Themable { } } - layout(dimension: Dimension): void { + layout(dimension: Dimension | undefined): void { this.workbenchDimensions = dimension; if (this._isVisible && this.notificationsCenterContainer) { @@ -264,7 +270,8 @@ export class NotificationsCenter extends Themable { } // Apply to list - this.notificationsList.layout(Math.min(maxWidth, availableWidth), Math.min(maxHeight, availableHeight)); + const notificationsList = assertIsDefined(this.notificationsList); + notificationsList.layout(Math.min(maxWidth, availableWidth), Math.min(maxHeight, availableHeight)); } } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index a2599e246ec..b2993d52599 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -16,10 +16,11 @@ import { NotificationsListDelegate, NotificationRenderer } from 'vs/workbench/br import { NotificationActionRunner, CopyNotificationMessageAction } from 'vs/workbench/browser/parts/notifications/notificationsActions'; import { NotificationFocusedContext } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; export class NotificationsList extends Themable { - private listContainer: HTMLElement; - private list: WorkbenchList; + private listContainer: HTMLElement | undefined; + private list: WorkbenchList | undefined; private viewModel: INotificationViewItem[]; private isVisible: boolean | undefined; @@ -38,7 +39,8 @@ export class NotificationsList extends Themable { show(focus?: boolean): void { if (this.isVisible) { if (focus) { - this.list.domFocus(); + const list = assertIsDefined(this.list); + list.domFocus(); } return; // already visible @@ -54,7 +56,8 @@ export class NotificationsList extends Themable { // Focus if (focus) { - this.list.domFocus(); + const list = assertIsDefined(this.list); + list.domFocus(); } } @@ -70,7 +73,7 @@ export class NotificationsList extends Themable { const renderer = this.instantiationService.createInstance(NotificationRenderer, actionRunner); // List - this.list = this._register(this.instantiationService.createInstance( + const list = this.list = this._register(this.instantiationService.createInstance( WorkbenchList, 'NotificationsList', this.listContainer, @@ -85,7 +88,7 @@ export class NotificationsList extends Themable { // Context menu to copy message const copyAction = this._register(this.instantiationService.createInstance(CopyNotificationMessageAction, CopyNotificationMessageAction.ID, CopyNotificationMessageAction.LABEL)); - this._register((this.list.onContextMenu(e => { + this._register((list.onContextMenu(e => { if (!e.element) { return; } @@ -99,27 +102,27 @@ export class NotificationsList extends Themable { }))); // Toggle on double click - this._register((this.list.onMouseDblClick(event => (event.element as INotificationViewItem).toggle()))); + this._register((list.onMouseDblClick(event => (event.element as INotificationViewItem).toggle()))); // Clear focus when DOM focus moves out // Use document.hasFocus() to not clear the focus when the entire window lost focus // This ensures that when the focus comes back, the notification is still focused - const listFocusTracker = this._register(trackFocus(this.list.getHTMLElement())); + const listFocusTracker = this._register(trackFocus(list.getHTMLElement())); this._register(listFocusTracker.onDidBlur(() => { if (document.hasFocus()) { - this.list.setFocus([]); + list.setFocus([]); } })); // Context key - NotificationFocusedContext.bindTo(this.list.contextKeyService); + NotificationFocusedContext.bindTo(list.contextKeyService); // Only allow for focus in notifications, as the // selection is too strong over the contents of // the notification - this._register(this.list.onSelectionChange(e => { + this._register(list.onSelectionChange(e => { if (e.indexes.length > 0) { - this.list.setSelection([]); + list.setSelection([]); } })); @@ -129,23 +132,24 @@ export class NotificationsList extends Themable { } updateNotificationsList(start: number, deleteCount: number, items: INotificationViewItem[] = []) { - const listHasDOMFocus = isAncestor(document.activeElement, this.listContainer); + const [list, listContainer] = assertAllDefined(this.list, this.listContainer); + const listHasDOMFocus = isAncestor(document.activeElement, listContainer); // Remember focus and relative top of that item - const focusedIndex = this.list.getFocus()[0]; + const focusedIndex = list.getFocus()[0]; const focusedItem = this.viewModel[focusedIndex]; let focusRelativeTop: number | null = null; if (typeof focusedIndex === 'number') { - focusRelativeTop = this.list.getRelativeTop(focusedIndex); + focusRelativeTop = list.getRelativeTop(focusedIndex); } // Update view model this.viewModel.splice(start, deleteCount, ...items); // Update list - this.list.splice(start, deleteCount, items); - this.list.layout(); + list.splice(start, deleteCount, items); + list.layout(); // Hide if no more notifications to show if (this.viewModel.length === 0) { @@ -167,15 +171,15 @@ export class NotificationsList extends Themable { } if (typeof focusRelativeTop === 'number') { - this.list.reveal(indexToFocus, focusRelativeTop); + list.reveal(indexToFocus, focusRelativeTop); } - this.list.setFocus([indexToFocus]); + list.setFocus([indexToFocus]); } // Restore DOM focus if we had focus before if (listHasDOMFocus) { - this.list.domFocus(); + list.domFocus(); } } @@ -204,7 +208,7 @@ export class NotificationsList extends Themable { } hasFocus(): boolean { - if (!this.isVisible || !this.list) { + if (!this.isVisible || !this.listContainer) { return false; // hidden } @@ -225,7 +229,7 @@ export class NotificationsList extends Themable { } layout(width: number, maxHeight?: number): void { - if (this.list) { + if (this.listContainer && this.list) { this.listContainer.style.width = `${width}px`; if (typeof maxHeight === 'number') { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 4be947506f2..ae1d7024b7e 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -23,6 +23,7 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { timeout } from 'vs/base/common/async'; +import { assertIsDefined } from 'vs/base/common/types'; interface INotificationToast { item: INotificationViewItem; @@ -52,8 +53,8 @@ export class NotificationsToasts extends Themable { return intervals; })(); - private notificationsToastsContainer: HTMLElement; - private workbenchDimensions: Dimension; + private notificationsToastsContainer: HTMLElement | undefined; + private workbenchDimensions: Dimension | undefined; private isNotificationsCenterVisible: boolean | undefined; private mapNotificationToToast: Map; private notificationsToastsVisibleContextKey: IContextKey; @@ -125,15 +126,16 @@ export class NotificationsToasts extends Themable { } // Lazily create toasts containers - if (!this.notificationsToastsContainer) { - this.notificationsToastsContainer = document.createElement('div'); - addClass(this.notificationsToastsContainer, 'notifications-toasts'); + let notificationsToastsContainer = this.notificationsToastsContainer; + if (!notificationsToastsContainer) { + notificationsToastsContainer = this.notificationsToastsContainer = document.createElement('div'); + addClass(notificationsToastsContainer, 'notifications-toasts'); - this.container.appendChild(this.notificationsToastsContainer); + this.container.appendChild(notificationsToastsContainer); } // Make Visible - addClass(this.notificationsToastsContainer, 'visible'); + addClass(notificationsToastsContainer, 'visible'); const itemDisposables = new DisposableStore(); @@ -141,11 +143,11 @@ export class NotificationsToasts extends Themable { const notificationToastContainer = document.createElement('div'); addClass(notificationToastContainer, 'notification-toast-container'); - const firstToast = this.notificationsToastsContainer.firstChild; + const firstToast = notificationsToastsContainer.firstChild; if (firstToast) { - this.notificationsToastsContainer.insertBefore(notificationToastContainer, firstToast); // always first + notificationsToastsContainer.insertBefore(notificationToastContainer, firstToast); // always first } else { - this.notificationsToastsContainer.appendChild(notificationToastContainer); + notificationsToastsContainer.appendChild(notificationToastContainer); } // Toast @@ -164,8 +166,8 @@ export class NotificationsToasts extends Themable { this.mapNotificationToToast.set(item, toast); itemDisposables.add(toDisposable(() => { - if (this.isVisible(toast)) { - this.notificationsToastsContainer.removeChild(toast.container); + if (this.isVisible(toast) && notificationsToastsContainer) { + notificationsToastsContainer.removeChild(toast.container); } })); @@ -318,7 +320,7 @@ export class NotificationsToasts extends Themable { } hide(): void { - const focusGroup = isAncestor(document.activeElement, this.notificationsToastsContainer); + const focusGroup = this.notificationsToastsContainer ? isAncestor(document.activeElement, this.notificationsToastsContainer) : false; this.removeToasts(); @@ -443,7 +445,7 @@ export class NotificationsToasts extends Themable { return notificationToasts.reverse(); // from newest to oldest } - layout(dimension: Dimension): void { + layout(dimension: Dimension | undefined): void { this.workbenchDimensions = dimension; const maxDimensions = this.computeMaxDimensions(); @@ -525,10 +527,11 @@ export class NotificationsToasts extends Themable { return; } + const notificationsToastsContainer = assertIsDefined(this.notificationsToastsContainer); if (visible) { - this.notificationsToastsContainer.appendChild(toast.container); + notificationsToastsContainer.appendChild(toast.container); } else { - this.notificationsToastsContainer.removeChild(toast.container); + notificationsToastsContainer.removeChild(toast.container); } } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 065c4fec998..aed3d39ee21 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -32,6 +32,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { values } from 'vs/base/common/map'; +import { assertIsDefined } from 'vs/base/common/types'; interface IPendingStatusbarEntry { id: string; @@ -337,14 +338,14 @@ export class StatusbarPart extends Part implements IStatusbarService { //#endregion - private styleElement: HTMLStyleElement; + private styleElement: HTMLStyleElement | undefined; private pendingEntries: IPendingStatusbarEntry[] = []; private readonly viewModel: StatusbarViewModel; - private leftItemsContainer: HTMLElement; - private rightItemsContainer: HTMLElement; + private leftItemsContainer: HTMLElement | undefined; + private rightItemsContainer: HTMLElement | undefined; constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -478,7 +479,7 @@ export class StatusbarPart extends Part implements IStatusbarService { ...this.viewModel.getEntries(StatusbarAlignment.LEFT), ...this.viewModel.getEntries(StatusbarAlignment.RIGHT).reverse() // reversing due to flex: row-reverse ].forEach(entry => { - const target = entry.alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer; + const target = assertIsDefined(entry.alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer); target.appendChild(entry.container); }); @@ -491,7 +492,7 @@ export class StatusbarPart extends Part implements IStatusbarService { entries.reverse(); // reversing due to flex: row-reverse } - const target = alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer; + const target = assertIsDefined(alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer); // find an entry that has lower priority than the new one // and then insert the item before that one diff --git a/src/vs/workbench/browser/quickopen.ts b/src/vs/workbench/browser/quickopen.ts index 230a461907f..0c4b67f1f29 100644 --- a/src/vs/workbench/browser/quickopen.ts +++ b/src/vs/workbench/browser/quickopen.ts @@ -3,11 +3,11 @@ * 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 * as arrays from 'vs/base/common/arrays'; -import * as strings from 'vs/base/common/strings'; -import * as types from 'vs/base/common/types'; +import { localize } from 'vs/nls'; +import { mixin, assign } from 'vs/base/common/objects'; +import { first } from 'vs/base/common/arrays'; +import { startsWith } from 'vs/base/common/strings'; +import { isString, assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen'; @@ -111,9 +111,9 @@ export class QuickOpenHandler { */ getEmptyLabel(searchString: string): string { if (searchString.length > 0) { - return nls.localize('noResultsMatching', "No results matching"); + return localize('noResultsMatching', "No results matching"); } - return nls.localize('noResultsFound2', "No results found"); + return localize('noResultsFound2', "No results found"); } } @@ -128,9 +128,9 @@ export interface QuickOpenHandlerHelpEntry { */ export class QuickOpenHandlerDescriptor { prefix: string; - description: string; + description?: string; contextKey?: string; - helpEntries: QuickOpenHandlerHelpEntry[]; + helpEntries?: QuickOpenHandlerHelpEntry[]; instantProgress: boolean; private id: string; @@ -145,7 +145,7 @@ export class QuickOpenHandlerDescriptor { this.contextKey = contextKey; this.instantProgress = instantProgress; - if (types.isString(param)) { + if (isString(param)) { this.description = param; } else { this.helpEntries = param; @@ -195,7 +195,7 @@ export interface IQuickOpenRegistry { class QuickOpenRegistry implements IQuickOpenRegistry { private handlers: QuickOpenHandlerDescriptor[] = []; - private defaultHandler: QuickOpenHandlerDescriptor; + private defaultHandler: QuickOpenHandlerDescriptor | undefined; registerQuickOpenHandler(descriptor: QuickOpenHandlerDescriptor): void { this.handlers.push(descriptor); @@ -214,11 +214,11 @@ class QuickOpenRegistry implements IQuickOpenRegistry { } getQuickOpenHandler(text: string): QuickOpenHandlerDescriptor | null { - return text ? (arrays.first(this.handlers, h => strings.startsWith(text, h.prefix)) || null) : null; + return text ? (first(this.handlers, h => startsWith(text, h.prefix)) || null) : null; } getDefaultQuickOpenHandler(): QuickOpenHandlerDescriptor { - return this.defaultHandler; + return assertIsDefined(this.defaultHandler); } } @@ -275,17 +275,17 @@ export class EditorQuickOpenEntry extends QuickOpenEntry implements IEditorQuick if (input instanceof EditorInput) { let opts = this.getOptions(); if (opts) { - opts = objects.mixin(opts, openOptions, true); + opts = mixin(opts, openOptions, true); } else if (openOptions) { opts = EditorOptions.create(openOptions); } - this.editorService.openEditor(input, types.withNullAsUndefined(opts), sideBySide ? SIDE_GROUP : ACTIVE_GROUP); + this.editorService.openEditor(input, withNullAsUndefined(opts), sideBySide ? SIDE_GROUP : ACTIVE_GROUP); } else { const resourceInput = input; if (openOptions) { - resourceInput.options = objects.assign(resourceInput.options || Object.create(null), openOptions); + resourceInput.options = assign(resourceInput.options || Object.create(null), openOptions); } this.editorService.openEditor(resourceInput, sideBySide ? SIDE_GROUP : ACTIVE_GROUP); diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 368e56b41c7..740f75d4a9f 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -21,6 +21,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IStorageService } from 'vs/platform/storage/common/storage'; import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; import { AbstractTree } from 'vs/base/browser/ui/tree/abstractTree'; +import { assertIsDefined } from 'vs/base/common/types'; export abstract class Viewlet extends Composite implements IViewlet { @@ -76,7 +77,7 @@ export const Extensions = { }; export class ViewletRegistry extends CompositeRegistry { - private defaultViewletId!: string; + private defaultViewletId: string | undefined; /** * Registers a viewlet to the platform. @@ -120,7 +121,7 @@ export class ViewletRegistry extends CompositeRegistry { * Gets the id of the viewlet that should open on startup by default. */ getDefaultViewletId(): string { - return this.defaultViewletId; + return assertIsDefined(this.defaultViewletId); } } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 1331b459d13..94d7bff9153 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -5,7 +5,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { assign } from 'vs/base/common/objects'; -import { isUndefinedOrNull } from 'vs/base/common/types'; +import { isUndefinedOrNull, withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { IEditor as ICodeEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon'; @@ -117,7 +117,7 @@ export interface ITextEditor extends IEditor { /** * Returns the underlying text editor widget of this editor. */ - getControl(): ICodeEditor; + getControl(): ICodeEditor | undefined; } export interface ITextDiffEditor extends IEditor { @@ -125,7 +125,7 @@ export interface ITextDiffEditor extends IEditor { /** * Returns the underlying text editor widget of this editor. */ - getControl(): IDiffEditor; + getControl(): IDiffEditor | undefined; } export interface ITextSideBySideEditor extends IEditor { @@ -827,13 +827,13 @@ export class EditorOptions implements IEditorOptions { * Base Text Editor Options. */ export class TextEditorOptions extends EditorOptions { - private startLineNumber: number; - private startColumn: number; - private endLineNumber: number; - private endColumn: number; + private startLineNumber: number | undefined; + private startColumn: number | undefined; + private endLineNumber: number | undefined; + private endColumn: number | undefined; - private revealInCenterIfOutsideViewport: boolean; - private editorViewState: IEditorViewState | null; + private revealInCenterIfOutsideViewport: boolean | undefined; + private editorViewState: IEditorViewState | undefined; static from(input?: IBaseResourceInput): TextEditorOptions | undefined { if (!input || !input.options) { @@ -901,7 +901,7 @@ export class TextEditorOptions extends EditorOptions { const options = TextEditorOptions.create(settings); // View state - options.editorViewState = editor.saveViewState(); + options.editorViewState = withNullAsUndefined(editor.saveViewState()); return options; } @@ -1084,23 +1084,23 @@ export interface IEditorMemento { } class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { - private instantiationService: IInstantiationService; - private fileInputFactory: IFileInputFactory; + private instantiationService: IInstantiationService | undefined; + private fileInputFactory: IFileInputFactory | undefined; private readonly editorInputFactoryConstructors: Map> = new Map(); private readonly editorInputFactoryInstances: Map = new Map(); start(accessor: ServicesAccessor): void { - this.instantiationService = accessor.get(IInstantiationService); + const instantiationService = this.instantiationService = accessor.get(IInstantiationService); this.editorInputFactoryConstructors.forEach((ctor, key) => { - this.createEditorInputFactory(key, ctor); + this.createEditorInputFactory(key, ctor, instantiationService); }); this.editorInputFactoryConstructors.clear(); } - private createEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0): void { - const instance = this.instantiationService.createInstance(ctor); + private createEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0, instantiationService: IInstantiationService): void { + const instance = instantiationService.createInstance(ctor); this.editorInputFactoryInstances.set(editorInputId, instance); } @@ -1109,14 +1109,14 @@ class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { } getFileInputFactory(): IFileInputFactory { - return this.fileInputFactory; + return assertIsDefined(this.fileInputFactory); } registerEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0): void { if (!this.instantiationService) { this.editorInputFactoryConstructors.set(editorInputId, ctor); } else { - this.createEditorInputFactory(editorInputId, ctor); + this.createEditorInputFactory(editorInputId, ctor, this.instantiationService); } } diff --git a/src/vs/workbench/common/editor/binaryEditorModel.ts b/src/vs/workbench/common/editor/binaryEditorModel.ts index 319f0a2c080..5f94a8c947a 100644 --- a/src/vs/workbench/common/editor/binaryEditorModel.ts +++ b/src/vs/workbench/common/editor/binaryEditorModel.ts @@ -14,7 +14,7 @@ import { MIME_BINARY } from 'vs/base/common/mime'; * An editor model that just represents a resource that can be loaded. */ export class BinaryEditorModel extends EditorModel { - private size: number; + private size: number | undefined; private etag: string | undefined; private readonly mime: string; @@ -27,6 +27,7 @@ export class BinaryEditorModel extends EditorModel { this.resource = resource; this.name = name; + this.mime = MIME_BINARY; if (resource.scheme === Schemas.data) { const metadata = DataUri.parseMetaData(resource); @@ -34,7 +35,10 @@ export class BinaryEditorModel extends EditorModel { this.size = Number(metadata.get(DataUri.META_DATA_SIZE)); } - this.mime = metadata.get(DataUri.META_DATA_MIME) || MIME_BINARY; + const metadataMime = metadata.get(DataUri.META_DATA_MIME); + if (metadataMime) { + this.mime = metadataMime; + } } } @@ -55,7 +59,7 @@ export class BinaryEditorModel extends EditorModel { /** * The size of the binary resource if known. */ - getSize(): number { + getSize(): number | undefined { return this.size; } diff --git a/src/vs/workbench/common/editor/diffEditorModel.ts b/src/vs/workbench/common/editor/diffEditorModel.ts index 2f3b4818e2b..f5c17787f90 100644 --- a/src/vs/workbench/common/editor/diffEditorModel.ts +++ b/src/vs/workbench/common/editor/diffEditorModel.ts @@ -11,6 +11,7 @@ import { IEditorModel } from 'vs/platform/editor/common/editor'; * and the modified version. */ export class DiffEditorModel extends EditorModel { + protected readonly _originalModel: IEditorModel | null; protected readonly _modifiedModel: IEditorModel | null; @@ -58,4 +59,4 @@ export class DiffEditorModel extends EditorModel { super.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/common/editor/textDiffEditorModel.ts b/src/vs/workbench/common/editor/textDiffEditorModel.ts index dc2f7405b98..f064fc3cab8 100644 --- a/src/vs/workbench/common/editor/textDiffEditorModel.ts +++ b/src/vs/workbench/common/editor/textDiffEditorModel.ts @@ -22,6 +22,9 @@ export class TextDiffEditorModel extends DiffEditorModel { constructor(originalModel: BaseTextEditorModel, modifiedModel: BaseTextEditorModel) { super(originalModel, modifiedModel); + this._originalModel = originalModel; + this._modifiedModel = modifiedModel; + this.updateTextDiffEditorModel(); } diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 463b4befe31..06d52c2e01d 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { isFunction } from 'vs/base/common/types'; +import { isFunction, assertIsDefined } from 'vs/base/common/types'; import { isValidBasename } from 'vs/base/common/extpath'; import { basename } from 'vs/base/common/resources'; import { Action } from 'vs/base/common/actions'; @@ -118,7 +118,8 @@ export class TextFileEditor extends BaseTextEditor { setOptions(options: EditorOptions | undefined): void { const textOptions = options as TextEditorOptions; if (textOptions && isFunction(textOptions.apply)) { - textOptions.apply(this.getControl(), ScrollType.Smooth); + const textEditor = assertIsDefined(this.getControl()); + textOptions.apply(textEditor, ScrollType.Smooth); } } @@ -147,7 +148,7 @@ export class TextFileEditor extends BaseTextEditor { const textFileModel = resolvedModel; // Editor - const textEditor = this.getControl(); + const textEditor = assertIsDefined(this.getControl()); textEditor.setModel(textFileModel.textEditorModel); // Always restore View State if any associated @@ -259,7 +260,10 @@ export class TextFileEditor extends BaseTextEditor { this.doSaveOrClearTextEditorViewState(this.input); // Clear Model - this.getControl().setModel(null); + const textEditor = this.getControl(); + if (textEditor) { + textEditor.setModel(null); + } // Pass to super super.clearInput(); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index 876c94e15cc..ba32cf2dda9 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -54,7 +54,7 @@ import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbe import { DefaultSettingsEditorModel, SettingsEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; +import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types'; export class PreferencesEditor extends BaseEditor { @@ -1049,20 +1049,25 @@ export class DefaultPreferencesEditor extends BaseTextEditor { return; } - this.getControl().setModel((editorModel).textEditorModel); + const editor = assertIsDefined(this.getControl()); + editor.setModel((editorModel).textEditorModel); })); } clearInput(): void { // Clear Model - this.getControl().setModel(null); + const editor = this.getControl(); + if (editor) { + editor.setModel(null); + } // Pass to super super.clearInput(); } layout(dimension: DOM.Dimension) { - this.getControl().layout(dimension); + const editor = assertIsDefined(this.getControl()); + editor.layout(dimension); } protected getAriaLabel(): string { diff --git a/src/vs/workbench/contrib/quickopen/browser/helpHandler.ts b/src/vs/workbench/contrib/quickopen/browser/helpHandler.ts index ac714337b35..8d8aaafcca2 100644 --- a/src/vs/workbench/contrib/quickopen/browser/helpHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/helpHandler.ts @@ -17,11 +17,11 @@ export const HELP_PREFIX = '?'; class HelpEntry extends QuickOpenEntryGroup { private prefixLabel: string; private prefix: string; - private description: string; + private description: string | undefined; private quickOpenService: IQuickOpenService; private openOnPreview: boolean; - constructor(prefix: string, description: string, quickOpenService: IQuickOpenService, openOnPreview: boolean) { + constructor(prefix: string, description: string | undefined, openOnPreview: boolean, quickOpenService: IQuickOpenService) { super(); if (!prefix) { @@ -44,7 +44,7 @@ class HelpEntry extends QuickOpenEntryGroup { return nls.localize('entryAriaLabel', "{0}, picker help", this.getLabel()); } - getDescription(): string { + getDescription(): string | undefined { return this.description; } @@ -101,9 +101,9 @@ export class HelpHandler extends QuickOpenHandler { matchingHandlers.forEach(handler => { if (handler instanceof QuickOpenHandlerDescriptor) { - workbenchScoped.push(new HelpEntry(handler.prefix, handler.description, this.quickOpenService, matchingHandlers.length === 1)); + workbenchScoped.push(new HelpEntry(handler.prefix, handler.description, matchingHandlers.length === 1, this.quickOpenService)); } else { - const entry = new HelpEntry(handler.prefix, handler.description, this.quickOpenService, matchingHandlers.length === 1); + const entry = new HelpEntry(handler.prefix, handler.description, matchingHandlers.length === 1, this.quickOpenService); if (handler.needsEditor) { editorScoped.push(entry); } else { diff --git a/src/vs/workbench/contrib/search/browser/replaceService.ts b/src/vs/workbench/contrib/search/browser/replaceService.ts index 502e32a326c..bc7e14ab2e2 100644 --- a/src/vs/workbench/contrib/search/browser/replaceService.ts +++ b/src/vs/workbench/contrib/search/browser/replaceService.ts @@ -130,7 +130,7 @@ export class ReplaceService implements IReplaceService { this.updateReplacePreview(fileMatch).then(() => { if (editor) { const editorControl = editor.getControl(); - if (element instanceof Match) { + if (element instanceof Match && editorControl) { editorControl.revealLineInCenter(element.range().startLineNumber, ScrollType.Immediate); } } diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index b81e66b0b7a..f68e4e20558 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -66,23 +66,21 @@ export class BrowserHostService extends Disposable implements IHostService { async open() { } }; } - - this.registerListeners(); } - private registerListeners(): void { + private _onDidChangeFocus: Event | undefined; + get onDidChangeFocus(): Event { + if (!this._onDidChangeFocus) { + const focusTracker = this._register(trackFocus(window)); + this._onDidChangeFocus = Event.any( + Event.map(focusTracker.onDidFocus, () => this.hasFocus), + Event.map(focusTracker.onDidBlur, () => this.hasFocus) + ); + } - // Track Focus on Window - const focusTracker = this._register(trackFocus(window)); - this._onDidChangeFocus = Event.any( - Event.map(focusTracker.onDidFocus, () => this.hasFocus), - Event.map(focusTracker.onDidBlur, () => this.hasFocus) - ); + return this._onDidChangeFocus; } - get onDidChangeFocus(): Event { return this._onDidChangeFocus; } - private _onDidChangeFocus: Event; - get hasFocus(): boolean { return document.hasFocus(); } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 20bc88bbf4f..19f35faaeaf 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -186,11 +186,11 @@ export class TestContextService implements IWorkspaceContextService { } export class TestTextFileService extends NativeTextFileService { - public cleanupBackupsBeforeShutdownCalled: boolean; + public cleanupBackupsBeforeShutdownCalled!: boolean; - private promptPath: URI; - private confirmResult: ConfirmResult; - private resolveTextContentError: FileOperationError | null; + private promptPath!: URI; + private confirmResult!: ConfirmResult; + private resolveTextContentError!: FileOperationError | null; constructor( @IWorkspaceContextService contextService: IWorkspaceContextService, @@ -762,7 +762,7 @@ export class TestEditorGroupsService implements IEditorGroupsService { return false; } - partOptions: IEditorPartOptions; + partOptions!: IEditorPartOptions; enforcePartOptions(options: IEditorPartOptions): IDisposable { return Disposable.None; } @@ -773,20 +773,20 @@ export class TestEditorGroup implements IEditorGroupView { constructor(public id: number) { } get group(): EditorGroup { throw new Error('not implemented'); } - activeControl: IVisibleEditor; - activeEditor: IEditorInput; - previewEditor: IEditorInput; - count: number; - disposed: boolean; + activeControl!: IVisibleEditor; + activeEditor!: IEditorInput; + previewEditor!: IEditorInput; + count!: number; + disposed!: boolean; editors: ReadonlyArray = []; - label: string; - index: number; + label!: string; + index!: number; whenRestored: Promise = Promise.resolve(undefined); - element: HTMLElement; - minimumWidth: number; - maximumWidth: number; - minimumHeight: number; - maximumHeight: number; + element!: HTMLElement; + minimumWidth!: number; + maximumWidth!: number; + minimumHeight!: number; + maximumHeight!: number; isEmpty = true; isMinimized = false; @@ -877,9 +877,9 @@ export class TestEditorService implements EditorServiceImpl { onDidCloseEditor: Event = Event.None; onDidOpenEditorFail: Event = Event.None; - activeControl: IVisibleEditor; + activeControl!: IVisibleEditor; activeTextEditorWidget: any; - activeEditor: IEditorInput; + activeEditor!: IEditorInput; editors: ReadonlyArray = []; visibleControls: ReadonlyArray = []; visibleTextEditorWidgets = []; @@ -929,7 +929,7 @@ export class TestFileService implements IFileService { readonly onError: Event = Event.None; private content = 'Hello Html'; - private lastReadFileUri: URI; + private lastReadFileUri!: URI; constructor() { this._onFileChanges = new Emitter(); @@ -1184,8 +1184,8 @@ export class TestLifecycleService implements ILifecycleService { public _serviceBrand: undefined; - public phase: LifecyclePhase; - public startupKind: StartupKind; + public phase!: LifecyclePhase; + public startupKind!: StartupKind; private readonly _onBeforeShutdown = new Emitter(); private readonly _onWillShutdown = new Emitter(); From cb0dc7680ebfbbb378ab5a717ca82a251836c489 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 10:53:53 +0200 Subject: [PATCH 203/435] debt - more strict init (#78168) --- src/vs/base/browser/ui/dropdown/dropdown.ts | 16 +- .../backup/electron-main/backupMainService.ts | 9 +- .../watcher/unix/chokidarWatcherService.ts | 4 +- .../lifecycle/common/lifecycleService.ts | 2 +- .../storage/browser/storageService.ts | 27 ++-- .../platform/storage/node/storageService.ts | 25 +-- .../telemetry/common/telemetryUtils.ts | 2 +- src/vs/workbench/browser/composite.ts | 29 ++-- src/vs/workbench/browser/layout.ts | 22 +-- src/vs/workbench/browser/panel.ts | 3 +- src/vs/workbench/browser/part.ts | 33 ++-- .../parts/activitybar/activitybarPart.ts | 24 +-- .../workbench/browser/parts/compositeBar.ts | 35 +++-- .../browser/parts/editor/editorControl.ts | 12 +- .../browser/parts/editor/tabsTitleControl.ts | 143 ++++++++++-------- .../browser/parts/panel/panelPart.ts | 12 +- .../browser/parts/sidebar/sidebarPart.ts | 3 +- .../browser/parts/statusbar/statusbarPart.ts | 2 +- src/vs/workbench/browser/viewlet.ts | 3 +- .../debug/browser/statusbarColorProvider.ts | 3 +- .../partsSplash.contribution.ts | 9 +- .../contrib/terminal/browser/terminalPanel.ts | 4 +- .../contrib/watermark/browser/watermark.ts | 7 +- .../browser/dynamicWebviewEditorOverlay.ts | 6 +- src/vs/workbench/electron-browser/window.ts | 4 +- .../services/history/browser/history.ts | 2 +- .../services/layout/browser/layoutService.ts | 4 +- .../textfile/common/textFileEditorModel.ts | 76 ++++------ .../textfile/test/textFileEditorModel.test.ts | 9 +- 29 files changed, 285 insertions(+), 245 deletions(-) diff --git a/src/vs/base/browser/ui/dropdown/dropdown.ts b/src/vs/base/browser/ui/dropdown/dropdown.ts index dd219559a59..c36015f710b 100644 --- a/src/vs/base/browser/ui/dropdown/dropdown.ts +++ b/src/vs/base/browser/ui/dropdown/dropdown.ts @@ -208,8 +208,8 @@ export interface IDropdownMenuOptions extends IBaseDropdownOptions { export class DropdownMenu extends BaseDropdown { private _contextMenuProvider: IContextMenuProvider; - private _menuOptions: IMenuOptions; - private _actions: ReadonlyArray; + private _menuOptions: IMenuOptions | undefined; + private _actions: ReadonlyArray = []; private actionProvider?: IActionProvider; private menuClassName: string; @@ -222,11 +222,11 @@ export class DropdownMenu extends BaseDropdown { this.menuClassName = options.menuClassName || ''; } - set menuOptions(options: IMenuOptions) { + set menuOptions(options: IMenuOptions | undefined) { this._menuOptions = options; } - get menuOptions(): IMenuOptions { + get menuOptions(): IMenuOptions | undefined { return this._menuOptions; } @@ -256,7 +256,7 @@ export class DropdownMenu extends BaseDropdown { getMenuClassName: () => this.menuClassName, onHide: () => this.onHide(), actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined, - anchorAlignment: this.menuOptions.anchorAlignment + anchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : AnchorAlignment.LEFT }); } @@ -345,7 +345,11 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem { super.setActionContext(newContext); if (this.dropdownMenu) { - this.dropdownMenu.menuOptions.context = newContext; + if (this.dropdownMenu.menuOptions) { + this.dropdownMenu.menuOptions.context = newContext; + } else { + this.dropdownMenu.menuOptions = { context: newContext }; + } } } diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index 5635ece6180..3d30e406440 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -28,9 +28,9 @@ export class BackupMainService implements IBackupMainService { protected backupHome: string; protected workspacesJsonPath: string; - private rootWorkspaces: IWorkspaceBackupInfo[]; - private folderWorkspaces: URI[]; - private emptyWorkspaces: IEmptyWindowBackupInfo[]; + private rootWorkspaces: IWorkspaceBackupInfo[] = []; + private folderWorkspaces: URI[] = []; + private emptyWorkspaces: IEmptyWindowBackupInfo[] = []; constructor( @IEnvironmentService environmentService: IEnvironmentService, @@ -55,8 +55,6 @@ export class BackupMainService implements IBackupMainService { } else if (Array.isArray(backups.emptyWorkspaces)) { // read legacy entries this.emptyWorkspaces = await this.validateEmptyWorkspaces(backups.emptyWorkspaces.map(backupFolder => ({ backupFolder }))); - } else { - this.emptyWorkspaces = []; } // read workspace backups @@ -70,6 +68,7 @@ export class BackupMainService implements IBackupMainService { } catch (e) { // ignore URI parsing exceptions } + this.rootWorkspaces = await this.validateWorkspaces(rootWorkspaces); // read folder backups diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index f12dfef68bc..d129ec844a9 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -32,8 +32,8 @@ export class ChokidarWatcherService implements IWatcherService { private static readonly FS_EVENT_DELAY = 50; // aggregate and only emit events when changes have stopped for this duration (in ms) private static readonly EVENT_SPAM_WARNING_THRESHOLD = 60 * 1000; // warn after certain time span of event spam - private _watchers: { [watchPath: string]: IWatcher }; - private _watcherCount: number; + private _watchers: { [watchPath: string]: IWatcher } = Object.create(null); + private _watcherCount = 0; private _pollingInterval?: number; private _usePolling?: boolean; diff --git a/src/vs/platform/lifecycle/common/lifecycleService.ts b/src/vs/platform/lifecycle/common/lifecycleService.ts index ea8b52b2492..1b2cb90c8af 100644 --- a/src/vs/platform/lifecycle/common/lifecycleService.ts +++ b/src/vs/platform/lifecycle/common/lifecycleService.ts @@ -23,7 +23,7 @@ export abstract class AbstractLifecycleService extends Disposable implements ILi protected readonly _onShutdown = this._register(new Emitter()); readonly onShutdown: Event = this._onShutdown.event; - protected _startupKind: StartupKind; + protected _startupKind: StartupKind = StartupKind.NewWindow; get startupKind(): StartupKind { return this._startupKind; } private _phase: LifecyclePhase = LifecyclePhase.Starting; diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 67f3e6ac6d0..e1da1af90f8 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -15,6 +15,7 @@ import { joinPath } from 'vs/base/common/resources'; import { runWhenIdle, RunOnceScheduler } from 'vs/base/common/async'; import { serializableToMap, mapToSerializable } from 'vs/base/common/map'; import { VSBuffer } from 'vs/base/common/buffer'; +import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; export class BrowserStorageService extends Disposable implements IStorageService { @@ -26,20 +27,20 @@ export class BrowserStorageService extends Disposable implements IStorageService private readonly _onWillSaveState: Emitter = this._register(new Emitter()); readonly onWillSaveState: Event = this._onWillSaveState.event; - private globalStorage: IStorage; - private workspaceStorage: IStorage; + private globalStorage: IStorage | undefined; + private workspaceStorage: IStorage | undefined; - private globalStorageDatabase: FileStorageDatabase; - private workspaceStorageDatabase: FileStorageDatabase; + private globalStorageDatabase: FileStorageDatabase | undefined; + private workspaceStorageDatabase: FileStorageDatabase | undefined; - private globalStorageFile: URI; - private workspaceStorageFile: URI; + private globalStorageFile: URI | undefined; + private workspaceStorageFile: URI | undefined; - private initializePromise: Promise; + private initializePromise: Promise | undefined; private periodicSaveScheduler = this._register(new RunOnceScheduler(() => this.collectState(), 5000)); get hasPendingUpdate(): boolean { - return this.globalStorageDatabase.hasPendingUpdate || this.workspaceStorageDatabase.hasPendingUpdate; + return (!!this.globalStorageDatabase && this.globalStorageDatabase.hasPendingUpdate) || (!!this.workspaceStorageDatabase && this.workspaceStorageDatabase.hasPendingUpdate); } constructor( @@ -137,16 +138,18 @@ export class BrowserStorageService extends Disposable implements IStorageService } private getStorage(scope: StorageScope): IStorage { - return scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage; + return assertIsDefined(scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage); } async logStorage(): Promise { + const [globalStorage, workspaceStorage, globalStorageFile, workspaceStorageFile] = assertAllDefined(this.globalStorage, this.workspaceStorage, this.globalStorageFile, this.workspaceStorageFile); + const result = await Promise.all([ - this.globalStorage.items, - this.workspaceStorage.items + globalStorage.items, + workspaceStorage.items ]); - return logStorage(result[0], result[1], this.globalStorageFile.toString(), this.workspaceStorageFile.toString()); + return logStorage(result[0], result[1], globalStorageFile.toString(), workspaceStorageFile.toString()); } async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise { diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index c0c777db385..bd4bbd98a22 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -15,6 +15,7 @@ import { copy, exists, mkdirp, writeFile } from 'vs/base/node/pfs'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkspaceInitializationPayload, isWorkspaceIdentifier, isSingleFolderWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces'; import { onUnexpectedError } from 'vs/base/common/errors'; +import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; export class NativeStorageService extends Disposable implements IStorageService { @@ -31,11 +32,11 @@ export class NativeStorageService extends Disposable implements IStorageService private globalStorage: IStorage; - private workspaceStoragePath: string; - private workspaceStorage: IStorage; - private workspaceStorageListener: IDisposable; + private workspaceStoragePath: string | undefined; + private workspaceStorage: IStorage | undefined; + private workspaceStorageListener: IDisposable | undefined; - private initializePromise: Promise; + private initializePromise: Promise | undefined; constructor( globalStorageDatabase: IStorageDatabase, @@ -191,22 +192,24 @@ export class NativeStorageService extends Disposable implements IStorageService // Do it await Promise.all([ - this.globalStorage.close(), - this.workspaceStorage.close() + this.getStorage(StorageScope.GLOBAL).close(), + this.getStorage(StorageScope.WORKSPACE).close() ]); } private getStorage(scope: StorageScope): IStorage { - return scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage; + return assertIsDefined(scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage); } async logStorage(): Promise { + const [workspaceStorage, workspaceStoragePath] = assertAllDefined(this.workspaceStorage, this.workspaceStoragePath); + const result = await Promise.all([ this.globalStorage.items, - this.workspaceStorage.items + workspaceStorage.items ]); - logStorage(result[0], result[1], this.environmentService.globalStorageHome, this.workspaceStoragePath); + logStorage(result[0], result[1], this.environmentService.globalStorageHome, workspaceStoragePath); } async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise { @@ -215,7 +218,7 @@ export class NativeStorageService extends Disposable implements IStorageService } // Close workspace DB to be able to copy - await this.workspaceStorage.close(); + await this.getStorage(StorageScope.WORKSPACE).close(); // Prepare new workspace storage folder const result = await this.prepareWorkspaceStorageFolder(toWorkspace); @@ -223,7 +226,7 @@ export class NativeStorageService extends Disposable implements IStorageService const newWorkspaceStoragePath = join(result.path, NativeStorageService.WORKSPACE_STORAGE_NAME); // Copy current storage over to new workspace storage - await copy(this.workspaceStoragePath, newWorkspaceStoragePath); + await copy(assertIsDefined(this.workspaceStoragePath), newWorkspaceStoragePath); // Recreate and init workspace storage return this.createWorkspaceStorage(newWorkspaceStoragePath).init(); diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index a8399a43946..520c211b51b 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -20,7 +20,7 @@ export const NullTelemetryService = new class implements ITelemetryService { return this.publicLog(eventName, data as ITelemetryData); } setEnabled() { } - isOptedIn: true; + isOptedIn = true; getTelemetryInfo(): Promise { return Promise.resolve({ instanceId: 'someValue.instanceId', diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index d29b5e51eaa..38dde654626 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -14,6 +14,7 @@ import { IConstructorSignature0, IInstantiationService } from 'vs/platform/insta import { trackFocus, Dimension } from 'vs/base/browser/dom'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { Disposable } from 'vs/base/common/lifecycle'; +import { assertIsDefined } from 'vs/base/common/types'; /** * Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite @@ -35,10 +36,10 @@ export abstract class Composite extends Component implements IComposite { private readonly _onDidChangeVisibility: Emitter = this._register(new Emitter()); readonly onDidChangeVisibility: Event = this._onDidChangeVisibility.event; - private _onDidFocus: Emitter; + private _onDidFocus: Emitter | undefined; get onDidFocus(): Event { if (!this._onDidFocus) { - this.registerFocusTrackEvents(); + this._onDidFocus = this.registerFocusTrackEvents().onDidFocus; } return this._onDidFocus.event; @@ -50,28 +51,32 @@ export abstract class Composite extends Component implements IComposite { } } - private _onDidBlur: Emitter; + private _onDidBlur: Emitter | undefined; get onDidBlur(): Event { if (!this._onDidBlur) { - this.registerFocusTrackEvents(); + this._onDidBlur = this.registerFocusTrackEvents().onDidBlur; } return this._onDidBlur.event; } - private registerFocusTrackEvents(): void { - this._onDidFocus = this._register(new Emitter()); - this._onDidBlur = this._register(new Emitter()); + private registerFocusTrackEvents(): { onDidFocus: Emitter, onDidBlur: Emitter } { + const container = assertIsDefined(this.getContainer()); + const focusTracker = this._register(trackFocus(container)); - const focusTracker = this._register(trackFocus(this.getContainer())); - this._register(focusTracker.onDidFocus(() => this._onDidFocus.fire())); - this._register(focusTracker.onDidBlur(() => this._onDidBlur.fire())); + const onDidFocus = this._onDidFocus = this._register(new Emitter()); + this._register(focusTracker.onDidFocus(() => onDidFocus.fire())); + + const onDidBlur = this._onDidBlur = this._register(new Emitter()); + this._register(focusTracker.onDidBlur(() => onDidBlur.fire())); + + return { onDidFocus, onDidBlur }; } protected actionRunner: IActionRunner | undefined; private visible: boolean; - private parent: HTMLElement; + private parent: HTMLElement | undefined; constructor( id: string, @@ -112,7 +117,7 @@ export abstract class Composite extends Component implements IComposite { /** * Returns the container this composite is being build in. */ - getContainer(): HTMLElement { + getContainer(): HTMLElement | undefined { return this.parent; } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 7da6d53387a..81593caec80 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -36,6 +36,7 @@ import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/a import { IFileService } from 'vs/platform/files/common/files'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { coalesce } from 'vs/base/common/arrays'; +import { assertIsDefined } from 'vs/base/common/types'; enum Settings { MENUBAR_VISIBLE = 'window.menuBarVisibility', @@ -340,10 +341,12 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.state.sideBar.position = position; // Adjust CSS - removeClass(activityBar.getContainer(), oldPositionValue); - removeClass(sideBar.getContainer(), oldPositionValue); - addClass(activityBar.getContainer(), newPositionValue); - addClass(sideBar.getContainer(), newPositionValue); + const activityBarContainer = assertIsDefined(activityBar.getContainer()); + const sideBarContainer = assertIsDefined(sideBar.getContainer()); + removeClass(activityBarContainer, oldPositionValue); + removeClass(sideBarContainer, oldPositionValue); + addClass(activityBarContainer, newPositionValue); + addClass(sideBarContainer, newPositionValue); // Update Styles activityBar.updateStyles(); @@ -528,10 +531,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi const container = this.getContainer(part); - return isAncestor(activeElement, container); + return !!container && isAncestor(activeElement, container); } - getContainer(part: Parts): HTMLElement { + getContainer(part: Parts): HTMLElement | undefined { switch (part) { case Parts.TITLEBAR_PART: return this.getPart(Parts.TITLEBAR_PART).getContainer(); @@ -579,7 +582,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi return true; // any other part cannot be hidden } - getDimension(part: Parts): Dimension { + getDimension(part: Parts): Dimension | undefined { return this.getPart(part).dimension; } @@ -1121,8 +1124,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.storageService.store(Storage.PANEL_POSITION, positionToString(this.state.panel.position), StorageScope.WORKSPACE); // Adjust CSS - removeClass(panelPart.getContainer(), oldPositionValue); - addClass(panelPart.getContainer(), newPositionValue); + const panelContainer = assertIsDefined(panelPart.getContainer()); + removeClass(panelContainer, oldPositionValue); + addClass(panelContainer, newPositionValue); // Update Styles panelPart.updateStyles(); diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index a3f613dead4..35da00194aa 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -112,8 +112,9 @@ export abstract class TogglePanelAction extends Action { private isPanelFocused(): boolean { const activeElement = document.activeElement; + const panelPart = this.layoutService.getContainer(Parts.PANEL_PART); - return !!(this.isPanelActive() && activeElement && isAncestor(activeElement, this.layoutService.getContainer(Parts.PANEL_PART))); + return !!(this.isPanelActive() && activeElement && panelPart && isAncestor(activeElement, panelPart)); } } diff --git a/src/vs/workbench/browser/part.ts b/src/vs/workbench/browser/part.ts index 80e0780610f..241d86e34ac 100644 --- a/src/vs/workbench/browser/part.ts +++ b/src/vs/workbench/browser/part.ts @@ -12,6 +12,7 @@ import { IDimension } from 'vs/platform/layout/browser/layoutService'; import { ISerializableView, IViewSize } from 'vs/base/browser/ui/grid/grid'; import { Event, Emitter } from 'vs/base/common/event'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { assertIsDefined } from 'vs/base/common/types'; export interface IPartOptions { hasTitle?: boolean; @@ -29,13 +30,13 @@ export interface ILayoutContentResult { */ export abstract class Part extends Component implements ISerializableView { - private _dimension: Dimension; - get dimension(): Dimension { return this._dimension; } + private _dimension: Dimension | undefined; + get dimension(): Dimension | undefined { return this._dimension; } - private parent: HTMLElement; - private titleArea: HTMLElement | null = null; - private contentArea: HTMLElement | null = null; - private partLayout: PartLayout; + private parent: HTMLElement | undefined; + private titleArea: HTMLElement | undefined; + private contentArea: HTMLElement | undefined; + private partLayout: PartLayout | undefined; constructor( id: string, @@ -80,35 +81,35 @@ export abstract class Part extends Component implements ISerializableView { /** * Returns the overall part container. */ - getContainer(): HTMLElement { + getContainer(): HTMLElement | undefined { return this.parent; } /** * Subclasses override to provide a title area implementation. */ - protected createTitleArea(parent: HTMLElement, options?: object): HTMLElement | null { - return null; + protected createTitleArea(parent: HTMLElement, options?: object): HTMLElement | undefined { + return undefined; } /** * Returns the title area container. */ - protected getTitleArea(): HTMLElement | null { + protected getTitleArea(): HTMLElement | undefined { return this.titleArea; } /** * Subclasses override to provide a content area implementation. */ - protected createContentArea(parent: HTMLElement, options?: object): HTMLElement | null { - return null; + protected createContentArea(parent: HTMLElement, options?: object): HTMLElement | undefined { + return undefined; } /** * Returns the content area container. */ - protected getContentArea(): HTMLElement | null { + protected getContentArea(): HTMLElement | undefined { return this.contentArea; } @@ -116,7 +117,9 @@ export abstract class Part extends Component implements ISerializableView { * Layout title and content area in the given dimension. */ protected layoutContents(width: number, height: number): ILayoutContentResult { - return this.partLayout.layout(width, height); + const partLayout = assertIsDefined(this.partLayout); + + return partLayout.layout(width, height); } //#region ISerializableView @@ -144,7 +147,7 @@ class PartLayout { private static readonly TITLE_HEIGHT = 35; - constructor(private options: IPartOptions, private contentArea: HTMLElement | null) { } + constructor(private options: IPartOptions, private contentArea: HTMLElement | undefined) { } layout(width: number, height: number): ILayoutContentResult { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 14848f29ec1..f45b3f776f4 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -30,7 +30,7 @@ import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IViewsService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewDescriptorCollection } from 'vs/workbench/common/views'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IViewlet } from 'vs/workbench/common/viewlet'; -import { isUndefinedOrNull } from 'vs/base/common/types'; +import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Schemas } from 'vs/base/common/network'; @@ -65,12 +65,12 @@ export class ActivitybarPart extends Part implements IActivityBarService { //#endregion - private globalActivityAction: ActivityAction; - private globalActivityActionBar: ActionBar; + private globalActivityAction: ActivityAction | undefined; + private globalActivityActionBar: ActionBar | undefined; private customMenubar: CustomMenubarControl | undefined; private menubar: HTMLElement | undefined; - private content: HTMLElement; + private content: HTMLElement | undefined; private cachedViewlets: ICachedViewlet[] = []; @@ -195,9 +195,11 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private showGlobalActivity(badge: IBadge, clazz?: string): IDisposable { - this.globalActivityAction.setBadge(badge, clazz); + const globalActivityAction = assertIsDefined(this.globalActivityAction); - return toDisposable(() => this.globalActivityAction.setBadge(undefined)); + globalActivityAction.setBadge(badge, clazz); + + return toDisposable(() => globalActivityAction.setBadge(undefined)); } private uninstallMenubar() { @@ -213,7 +215,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { private installMenubar() { this.menubar = document.createElement('div'); addClass(this.menubar, 'menubar'); - this.content.prepend(this.menubar); + + const content = assertIsDefined(this.content); + content.prepend(this.menubar); // Menubar: install a custom menu bar depending on configuration this.customMenubar = this._register(this.instantiationService.createInstance(CustomMenubarControl)); @@ -252,7 +256,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { super.updateStyles(); // Part container - const container = this.getContainer(); + const container = assertIsDefined(this.getContainer()); const background = this.getColor(ACTIVITY_BAR_BACKGROUND); container.style.backgroundColor = background; @@ -440,7 +444,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void { if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL && this.cachedViewletsValue !== this.getStoredCachedViewletsValue() /* This checks if current window changed the value or not */) { - this._cachedViewletsValue = null; + this._cachedViewletsValue = undefined; const newCompositeItems: ICompositeBarItem[] = []; const compositeItems = this.compositeBar.getCompositeBarItems(); const cachedViewlets = this.getCachedViewlets(); @@ -525,7 +529,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { return result; } - private _cachedViewletsValue: string | null; + private _cachedViewletsValue: string | undefined; private get cachedViewletsValue(): string { if (!this._cachedViewletsValue) { this._cachedViewletsValue = this.getStoredCachedViewletsValue(); diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index b7a7d47044a..33495bbc8de 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -48,7 +48,7 @@ export class CompositeBar extends Widget implements ICompositeBar { private dimension: Dimension | undefined; - private compositeSwitcherBar: ActionBar; + private compositeSwitcherBar: ActionBar | undefined; private compositeOverflowAction: CompositeOverflowActivityAction | undefined; private compositeOverflowActionViewItem: CompositeOverflowActivityActionViewItem | undefined; @@ -92,6 +92,7 @@ export class CompositeBar extends Widget implements ICompositeBar { create(parent: HTMLElement): HTMLElement { const actionBarDiv = parent.appendChild($('.composite-bar')); + this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, { actionViewItemProvider: (action: Action) => { if (action instanceof CompositeOverflowActivityAction) { @@ -281,21 +282,23 @@ export class CompositeBar extends Widget implements ICompositeBar { if (size) { items.forEach(composite => this.compositeSizeInBar.set(composite.id, size)); } else { - if (this.dimension && this.dimension.height !== 0 && this.dimension.width !== 0) { + const compositeSwitcherBar = this.compositeSwitcherBar; + if (compositeSwitcherBar && this.dimension && this.dimension.height !== 0 && this.dimension.width !== 0) { // Compute sizes only if visible. Otherwise the size measurment would be computed wrongly. - const currentItemsLength = this.compositeSwitcherBar.viewItems.length; - this.compositeSwitcherBar.push(items.map(composite => composite.activityAction)); + const currentItemsLength = compositeSwitcherBar.viewItems.length; + compositeSwitcherBar.push(items.map(composite => composite.activityAction)); items.map((composite, index) => this.compositeSizeInBar.set(composite.id, this.options.orientation === ActionsOrientation.VERTICAL - ? this.compositeSwitcherBar.getHeight(currentItemsLength + index) - : this.compositeSwitcherBar.getWidth(currentItemsLength + index) + ? compositeSwitcherBar.getHeight(currentItemsLength + index) + : compositeSwitcherBar.getWidth(currentItemsLength + index) )); - items.forEach(() => this.compositeSwitcherBar.pull(this.compositeSwitcherBar.viewItems.length - 1)); + items.forEach(() => compositeSwitcherBar.pull(compositeSwitcherBar.viewItems.length - 1)); } } } private updateCompositeSwitcher(): void { - if (!this.compositeSwitcherBar || !this.dimension) { + const compositeSwitcherBar = this.compositeSwitcherBar; + if (!compositeSwitcherBar || !this.dimension) { return; // We have not been rendered yet so there is nothing to update. } @@ -343,7 +346,7 @@ export class CompositeBar extends Widget implements ICompositeBar { // 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); + compositeSwitcherBar.pull(compositeSwitcherBar.length() - 1); this.compositeOverflowAction.dispose(); this.compositeOverflowAction = undefined; @@ -362,8 +365,8 @@ export class CompositeBar extends Widget implements ICompositeBar { } }); compositesToRemove.reverse().forEach(index => { - const actionViewItem = this.compositeSwitcherBar.viewItems[index]; - this.compositeSwitcherBar.pull(index); + const actionViewItem = compositeSwitcherBar.viewItems[index]; + compositeSwitcherBar.pull(index); actionViewItem.dispose(); this.visibleComposites.splice(index, 1); }); @@ -373,19 +376,19 @@ export class CompositeBar extends Widget implements ICompositeBar { const currentIndex = this.visibleComposites.indexOf(compositeId); if (newIndex !== currentIndex) { if (currentIndex !== -1) { - const actionViewItem = this.compositeSwitcherBar.viewItems[currentIndex]; - this.compositeSwitcherBar.pull(currentIndex); + const actionViewItem = compositeSwitcherBar.viewItems[currentIndex]; + compositeSwitcherBar.pull(currentIndex); actionViewItem.dispose(); this.visibleComposites.splice(currentIndex, 1); } - this.compositeSwitcherBar.push(this.model.findItem(compositeId).activityAction, { label: true, icon: this.options.icon, index: newIndex }); + compositeSwitcherBar.push(this.model.findItem(compositeId).activityAction, { label: true, icon: this.options.icon, index: newIndex }); this.visibleComposites.splice(newIndex, 0, compositeId); } }); // Add overflow action as needed - if ((visibleCompositesChange && overflows) || this.compositeSwitcherBar.length() === 0) { + if ((visibleCompositesChange && overflows) || compositeSwitcherBar.length() === 0) { this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => { if (this.compositeOverflowActionViewItem) { this.compositeOverflowActionViewItem.showMenu(); @@ -404,7 +407,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this.options.colors ); - this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true }); + compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true }); } this._onDidChange.fire(); diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index 898d7339fef..f96a342299a 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -15,6 +15,7 @@ import { IEditorProgressService, LongRunningOperation } from 'vs/platform/progre import { IEditorGroupView, DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor'; import { Event, Emitter } from 'vs/base/common/event'; import { IVisibleEditor } from 'vs/workbench/services/editor/common/editorService'; +import { assertIsDefined } from 'vs/base/common/types'; export interface IOpenEditorResult { readonly control: BaseEditor; @@ -88,8 +89,9 @@ export class EditorControl extends Disposable { this.doSetActiveControl(control); // Show editor - this.parent.appendChild(control.getContainer()); - show(control.getContainer()); + const container = assertIsDefined(control.getContainer()); + this.parent.appendChild(container); + show(container); // Indicate to editor that it is now visible control.setVisible(true, this.groupView); @@ -203,8 +205,10 @@ export class EditorControl extends Disposable { // Remove control from parent and hide const controlInstanceContainer = this._activeControl.getContainer(); - this.parent.removeChild(controlInstanceContainer); - hide(controlInstanceContainer); + if (controlInstanceContainer) { + this.parent.removeChild(controlInstanceContainer); + hide(controlInstanceContainer); + } // Indicate to editor control this._activeControl.clearInput(); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index b993b3a5b05..2fc4adaf8db 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -40,7 +40,7 @@ import { CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorAc import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl'; import { IFileService } from 'vs/platform/files/common/files'; -import { withNullAsUndefined } from 'vs/base/common/types'; +import { withNullAsUndefined, assertAllDefined, assertIsDefined } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; interface IEditorInputLabel { @@ -53,19 +53,20 @@ type AugmentedLabel = IEditorInputLabel & { editor: IEditorInput }; export class TabsTitleControl extends TitleControl { - private titleContainer: HTMLElement; - private tabsContainer: HTMLElement; - private editorToolbarContainer: HTMLElement; - private tabsScrollbar: ScrollableElement; + private titleContainer: HTMLElement | undefined; + private tabsContainer: HTMLElement | undefined; + private editorToolbarContainer: HTMLElement | undefined; + private tabsScrollbar: ScrollableElement | undefined; + private closeOneEditorAction: CloseOneEditorAction; private tabResourceLabels: ResourceLabels; private tabLabels: IEditorInputLabel[] = []; private tabDisposables: IDisposable[] = []; - private dimension: Dimension; + private dimension: Dimension | undefined; private readonly layoutScheduled = this._register(new MutableDisposable()); - private blockRevealActiveTab: boolean; + private blockRevealActiveTab: boolean | undefined; constructor( parent: HTMLElement, @@ -87,6 +88,9 @@ export class TabsTitleControl extends TitleControl { @ILabelService labelService: ILabelService ) { super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService, labelService); + + this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER)); + this.closeOneEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL)); } protected create(parent: HTMLElement): void { @@ -103,13 +107,13 @@ export class TabsTitleControl extends TitleControl { this.tabsContainer.draggable = true; addClass(this.tabsContainer, 'tabs-container'); - // Tabs Container listeners - this.registerTabsContainerListeners(); - // Tabs Scrollbar this.tabsScrollbar = this._register(this.createTabsScrollbar(this.tabsContainer)); tabsAndActionsContainer.appendChild(this.tabsScrollbar.getDomNode()); + // Tabs Container listeners + this.registerTabsContainerListeners(this.tabsContainer, this.tabsScrollbar); + // Editor Toolbar Container this.editorToolbarContainer = document.createElement('div'); addClass(this.editorToolbarContainer, 'editor-actions'); @@ -118,17 +122,11 @@ export class TabsTitleControl extends TitleControl { // Editor Actions Toolbar this.createEditorActionsToolBar(this.editorToolbarContainer); - // Close Action - this.closeOneEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL)); - // Breadcrumbs (are on a separate row below tabs and actions) const breadcrumbsContainer = document.createElement('div'); addClass(breadcrumbsContainer, 'tabs-breadcrumbs'); this.titleContainer.appendChild(breadcrumbsContainer); this.createBreadcrumbsControl(breadcrumbsContainer, { showFileIcons: true, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: breadcrumbsBackground }); - - // Tab Labels - this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER)); } private createTabsScrollbar(scrollable: HTMLElement): ScrollableElement { @@ -160,23 +158,23 @@ export class TabsTitleControl extends TitleControl { this.group.relayout(); } - private registerTabsContainerListeners(): void { + private registerTabsContainerListeners(tabsContainer: HTMLElement, tabsScrollbar: ScrollableElement): void { // Group dragging - this.enableGroupDragging(this.tabsContainer); + this.enableGroupDragging(tabsContainer); // Forward scrolling inside the container to our custom scrollbar - this._register(addDisposableListener(this.tabsContainer, EventType.SCROLL, () => { - if (hasClass(this.tabsContainer, 'scroll')) { - this.tabsScrollbar.setScrollPosition({ - scrollLeft: this.tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar + this._register(addDisposableListener(tabsContainer, EventType.SCROLL, () => { + if (hasClass(tabsContainer, 'scroll')) { + tabsScrollbar.setScrollPosition({ + scrollLeft: tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar }); } })); // New file when double clicking on tabs container (but not tabs) - this._register(addDisposableListener(this.tabsContainer, EventType.DBLCLICK, e => { - if (e.target === this.tabsContainer) { + this._register(addDisposableListener(tabsContainer, EventType.DBLCLICK, e => { + if (e.target === tabsContainer) { EventHelper.stop(e); this.group.openEditor(this.untitledEditorService.createOrGet(), { pinned: true /* untitled is always pinned */, index: this.group.count /* always at the end */ }); @@ -184,23 +182,22 @@ export class TabsTitleControl extends TitleControl { })); // Prevent auto-scrolling (https://github.com/Microsoft/vscode/issues/16690) - this._register(addDisposableListener(this.tabsContainer, EventType.MOUSE_DOWN, (e: MouseEvent) => { + this._register(addDisposableListener(tabsContainer, EventType.MOUSE_DOWN, (e: MouseEvent) => { if (e.button === 1) { e.preventDefault(); } })); - // Drop support - this._register(new DragAndDropObserver(this.tabsContainer, { + this._register(new DragAndDropObserver(tabsContainer, { onDragEnter: e => { // Always enable support to scroll while dragging - addClass(this.tabsContainer, 'scroll'); + addClass(tabsContainer, 'scroll'); // Return if the target is not on the tabs container - if (e.target !== this.tabsContainer) { - this.updateDropFeedback(this.tabsContainer, false); // fixes https://github.com/Microsoft/vscode/issues/52093 + if (e.target !== tabsContainer) { + this.updateDropFeedback(tabsContainer, false); // fixes https://github.com/Microsoft/vscode/issues/52093 return; } @@ -239,25 +236,25 @@ export class TabsTitleControl extends TitleControl { } } - this.updateDropFeedback(this.tabsContainer, true); + this.updateDropFeedback(tabsContainer, true); }, onDragLeave: e => { - this.updateDropFeedback(this.tabsContainer, false); - removeClass(this.tabsContainer, 'scroll'); + this.updateDropFeedback(tabsContainer, false); + removeClass(tabsContainer, 'scroll'); }, onDragEnd: e => { - this.updateDropFeedback(this.tabsContainer, false); - removeClass(this.tabsContainer, 'scroll'); + this.updateDropFeedback(tabsContainer, false); + removeClass(tabsContainer, 'scroll'); }, onDrop: e => { - this.updateDropFeedback(this.tabsContainer, false); - removeClass(this.tabsContainer, 'scroll'); + this.updateDropFeedback(tabsContainer, false); + removeClass(tabsContainer, 'scroll'); - if (e.target === this.tabsContainer) { - this.onDrop(e, this.group.count); + if (e.target === tabsContainer) { + this.onDrop(e, this.group.count, tabsContainer); } } })); @@ -274,8 +271,9 @@ export class TabsTitleControl extends TitleControl { openEditor(editor: IEditorInput): void { // Create tabs as needed - for (let i = this.tabsContainer.children.length; i < this.group.count; i++) { - this.tabsContainer.appendChild(this.createTab(i)); + const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar); + for (let i = tabsContainer.children.length; i < this.group.count; i++) { + tabsContainer.appendChild(this.createTab(i, tabsContainer, tabsScrollbar)); } // An add of a tab requires to recompute all labels @@ -306,10 +304,11 @@ export class TabsTitleControl extends TitleControl { if (this.group.activeEditor) { // Remove tabs that got closed - while (this.tabsContainer.children.length > this.group.count) { + const tabsContainer = assertIsDefined(this.tabsContainer); + while (tabsContainer.children.length > this.group.count) { // Remove one tab from container (must be the last to keep indexes in order!) - (this.tabsContainer.lastChild as HTMLElement).remove(); + (tabsContainer.lastChild as HTMLElement).remove(); // Remove associated tab label and widget this.tabDisposables.pop()!.dispose(); @@ -324,7 +323,9 @@ export class TabsTitleControl extends TitleControl { // No tabs to show else { - clearNode(this.tabsContainer); + if (this.tabsContainer) { + clearNode(this.tabsContainer); + } this.tabDisposables = dispose(this.tabDisposables); this.tabResourceLabels.clear(); @@ -420,13 +421,14 @@ export class TabsTitleControl extends TitleControl { private withTab(editor: IEditorInput, fn: (tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void { const editorIndex = this.group.getIndexOfEditor(editor); - const tabContainer = this.tabsContainer.children[editorIndex] as HTMLElement; + const tabsContainer = assertIsDefined(this.tabsContainer); + const tabContainer = tabsContainer.children[editorIndex] as HTMLElement; if (tabContainer) { fn(tabContainer, this.tabResourceLabels.get(editorIndex), this.tabLabels[editorIndex]); } } - private createTab(index: number): HTMLElement { + private createTab(index: number, tabsContainer: HTMLElement, tabsScrollbar: ScrollableElement): HTMLElement { // Tab Container const tabContainer = document.createElement('div'); @@ -463,14 +465,14 @@ export class TabsTitleControl extends TitleControl { tabActionBar.onDidBeforeRun(() => this.blockRevealActiveTabOnce()); // Eventing - const eventsDisposable = this.registerTabListeners(tabContainer, index); + const eventsDisposable = this.registerTabListeners(tabContainer, index, tabsContainer, tabsScrollbar); this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBar, tabActionRunner, editorLabel)); return tabContainer; } - private registerTabListeners(tab: HTMLElement, index: number): IDisposable { + private registerTabListeners(tab: HTMLElement, index: number, tabsContainer: HTMLElement, tabsScrollbar: ScrollableElement): IDisposable { const disposables = new DisposableStore(); const handleClickOrTouch = (e: MouseEvent | GestureEvent): void => { @@ -512,7 +514,7 @@ export class TabsTitleControl extends TitleControl { // Touch Scroll Support disposables.add(addDisposableListener(tab, TouchEventType.Change, (e: GestureEvent) => { - this.tabsScrollbar.setScrollPosition({ scrollLeft: this.tabsScrollbar.getScrollPosition().scrollLeft - e.translationX }); + tabsScrollbar.setScrollPosition({ scrollLeft: tabsScrollbar.getScrollPosition().scrollLeft - e.translationX }); })); // Close on mouse middle click @@ -573,7 +575,7 @@ export class TabsTitleControl extends TitleControl { if (target) { handled = true; this.group.openEditor(target, { preserveFocus: true }); - (this.tabsContainer.childNodes[targetIndex]).focus(); + (tabsContainer.childNodes[targetIndex]).focus(); } } @@ -582,8 +584,8 @@ export class TabsTitleControl extends TitleControl { } // moving in the tabs container can have an impact on scrolling position, so we need to update the custom scrollbar - this.tabsScrollbar.setScrollPosition({ - scrollLeft: this.tabsContainer.scrollLeft + tabsScrollbar.setScrollPosition({ + scrollLeft: tabsContainer.scrollLeft }); })); @@ -689,7 +691,7 @@ export class TabsTitleControl extends TitleControl { removeClass(tab, 'dragged-over'); this.updateDropFeedback(tab, false, index); - this.onDrop(e, index); + this.onDrop(e, index, tabsContainer); } })); @@ -862,7 +864,8 @@ export class TabsTitleControl extends TitleControl { private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void { this.group.editors.forEach((editor, index) => { - const tabContainer = this.tabsContainer.children[index] as HTMLElement; + const tabsContainer = assertIsDefined(this.tabsContainer); + const tabContainer = tabsContainer.children[index] as HTMLElement; if (tabContainer) { fn(editor, index, tabContainer, this.tabResourceLabels.get(index), this.tabLabels[index]); } @@ -1012,7 +1015,7 @@ export class TabsTitleControl extends TitleControl { return hasModifiedBorderColor; } - layout(dimension: Dimension): void { + layout(dimension: Dimension | undefined): void { this.dimension = dimension; const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined; @@ -1025,7 +1028,9 @@ export class TabsTitleControl extends TitleControl { // this a little bit we try at least to schedule this work on the next animation frame. if (!this.layoutScheduled.value) { this.layoutScheduled.value = scheduleAtNextAnimationFrame(() => { - this.doLayout(this.dimension); + const dimension = assertIsDefined(this.dimension); + this.doLayout(dimension); + this.layoutScheduled.clear(); }); } @@ -1037,13 +1042,15 @@ export class TabsTitleControl extends TitleControl { return; } + const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar); + if (this.breadcrumbsControl && !this.breadcrumbsControl.isHidden()) { this.breadcrumbsControl.layout({ width: dimension.width, height: BreadcrumbsControl.HEIGHT }); - this.tabsScrollbar.getDomNode().style.height = `${dimension.height - BreadcrumbsControl.HEIGHT}px`; + tabsScrollbar.getDomNode().style.height = `${dimension.height - BreadcrumbsControl.HEIGHT}px`; } - const visibleContainerWidth = this.tabsContainer.offsetWidth; - const totalContainerWidth = this.tabsContainer.scrollWidth; + const visibleContainerWidth = tabsContainer.offsetWidth; + const totalContainerWidth = tabsContainer.scrollWidth; let activeTabPosX: number | undefined; let activeTabWidth: number | undefined; @@ -1054,7 +1061,7 @@ export class TabsTitleControl extends TitleControl { } // Update scrollbar - this.tabsScrollbar.setScrollDimensions({ + tabsScrollbar.setScrollDimensions({ width: visibleContainerWidth, scrollWidth: totalContainerWidth }); @@ -1066,20 +1073,20 @@ export class TabsTitleControl extends TitleControl { } // Reveal the active one - const containerScrollPosX = this.tabsScrollbar.getScrollPosition().scrollLeft; + const containerScrollPosX = tabsScrollbar.getScrollPosition().scrollLeft; const activeTabFits = activeTabWidth <= visibleContainerWidth; // Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right // Note: only try to do this if we actually have enough width to give to show the tab fully! if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) { - this.tabsScrollbar.setScrollPosition({ + tabsScrollbar.setScrollPosition({ scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */) }); } // Tab is overlflowng to the left or does not fit: Scroll it into view to the left else if (containerScrollPosX > activeTabPosX || !activeTabFits) { - this.tabsScrollbar.setScrollPosition({ + tabsScrollbar.setScrollPosition({ scrollLeft: activeTabPosX }); } @@ -1088,7 +1095,9 @@ export class TabsTitleControl extends TitleControl { private getTab(editor: IEditorInput): HTMLElement | undefined { const editorIndex = this.group.getIndexOfEditor(editor); if (editorIndex >= 0) { - return this.tabsContainer.children[editorIndex] as HTMLElement; + const tabsContainer = assertIsDefined(this.tabsContainer); + + return tabsContainer.children[editorIndex] as HTMLElement; } return undefined; @@ -1115,11 +1124,11 @@ export class TabsTitleControl extends TitleControl { return !!findParentWithClass(element, 'action-item', 'tab'); } - private onDrop(e: DragEvent, targetIndex: number): void { + private onDrop(e: DragEvent, targetIndex: number, tabsContainer: HTMLElement): void { EventHelper.stop(e, true); - this.updateDropFeedback(this.tabsContainer, false); - removeClass(this.tabsContainer, 'scroll'); + this.updateDropFeedback(tabsContainer, false); + removeClass(tabsContainer, 'scroll'); // Local Editor DND if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 05f24184cfb..bfec292330a 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -30,7 +30,7 @@ import { Dimension, trackFocus } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, withUndefinedAsNull, withNullAsUndefined } from 'vs/base/common/types'; +import { isUndefinedOrNull, withUndefinedAsNull, withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -60,13 +60,13 @@ export class PanelPart extends CompositePart implements IPanelService { readonly snap = true; get preferredHeight(): number | undefined { - const sidebarDimension = this.layoutService.getDimension(Parts.SIDEBAR_PART); + const sidebarDimension = assertIsDefined(this.layoutService.getDimension(Parts.SIDEBAR_PART)); return sidebarDimension.height * 0.4; } get preferredWidth(): number | undefined { - const statusbarPart = this.layoutService.getDimension(Parts.STATUSBAR_PART); - return statusbarPart.width * 0.4; + const statusbarDimension = assertIsDefined(this.layoutService.getDimension(Parts.STATUSBAR_PART)); + return statusbarDimension.width * 0.4; } //#endregion @@ -208,7 +208,7 @@ export class PanelPart extends CompositePart implements IPanelService { updateStyles(): void { super.updateStyles(); - const container = this.getContainer(); + const container = assertIsDefined(this.getContainer()); container.style.backgroundColor = this.getColor(PANEL_BACKGROUND); container.style.borderLeftColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder); @@ -316,7 +316,7 @@ export class PanelPart extends CompositePart implements IPanelService { } private layoutCompositeBar(): void { - if (this._contentDimension) { + if (this._contentDimension && this.dimension) { let availableWidth = this._contentDimension.width - 40; // take padding into account if (this.toolBar) { availableWidth = Math.max(PanelPart.MIN_COMPOSITE_BAR_WIDTH, availableWidth - this.getToolbarWidth()); // adjust height for global actions showing diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index f4b35007b80..a4a949af32e 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -32,6 +32,7 @@ import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { LayoutPriority } from 'vs/base/browser/ui/grid/grid'; +import { assertIsDefined } from 'vs/base/common/types'; export class SidebarPart extends CompositePart implements IViewletService { @@ -173,7 +174,7 @@ export class SidebarPart extends CompositePart implements IViewletServi super.updateStyles(); // Part container - const container = this.getContainer(); + const container = assertIsDefined(this.getContainer()); container.style.backgroundColor = this.getColor(SIDE_BAR_BACKGROUND); container.style.color = this.getColor(SIDE_BAR_FOREGROUND); diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index aed3d39ee21..11ec913abd8 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -575,7 +575,7 @@ export class StatusbarPart extends Part implements IStatusbarService { updateStyles(): void { super.updateStyles(); - const container = this.getContainer(); + const container = assertIsDefined(this.getContainer()); // Background colors const backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND); diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 740f75d4a9f..35b8233db03 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -167,8 +167,9 @@ export class ShowViewletAction extends Action { private sidebarHasFocus(): boolean { const activeViewlet = this.viewletService.getActiveViewlet(); const activeElement = document.activeElement; + const sidebarPart = this.layoutService.getContainer(Parts.SIDEBAR_PART); - return !!(activeViewlet && activeElement && DOM.isAncestor(activeElement, this.layoutService.getContainer(Parts.SIDEBAR_PART))); + return !!(activeViewlet && activeElement && sidebarPart && DOM.isAncestor(activeElement, sidebarPart)); } } diff --git a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts index 6078564168b..20d1d4a6a25 100644 --- a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts +++ b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts @@ -12,6 +12,7 @@ import { IDebugService, State } from 'vs/workbench/contrib/debug/common/debug'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_BACKGROUND, Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_BORDER } from 'vs/workbench/common/theme'; import { addClass, removeClass, createStyleSheet } from 'vs/base/browser/dom'; +import { assertIsDefined } from 'vs/base/common/types'; // colors for theming @@ -56,7 +57,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri protected updateStyles(): void { super.updateStyles(); - const container = this.layoutService.getContainer(Parts.STATUSBAR_PART); + const container = assertIsDefined(this.layoutService.getContainer(Parts.STATUSBAR_PART)); if (isStatusbarInDebugMode(this.debugService)) { addClass(container, 'debugging'); } else { diff --git a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts index 657096ea265..69b99fd7c0b 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -25,6 +25,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import * as perf from 'vs/base/common/performance'; import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService'; +import { assertIsDefined } from 'vs/base/common/types'; class PartsSplash { @@ -81,10 +82,10 @@ class PartsSplash { const layoutInfo = !this._shouldSaveLayoutInfo() ? undefined : { sideBarSide: this._layoutService.getSideBarPosition() === Position.RIGHT ? 'right' : 'left', editorPartMinWidth: DEFAULT_EDITOR_MIN_DIMENSIONS.width, - titleBarHeight: this._layoutService.isVisible(Parts.TITLEBAR_PART) ? getTotalHeight(this._layoutService.getContainer(Parts.TITLEBAR_PART)) : 0, - activityBarWidth: this._layoutService.isVisible(Parts.ACTIVITYBAR_PART) ? getTotalWidth(this._layoutService.getContainer(Parts.ACTIVITYBAR_PART)) : 0, - sideBarWidth: this._layoutService.isVisible(Parts.SIDEBAR_PART) ? getTotalWidth(this._layoutService.getContainer(Parts.SIDEBAR_PART)) : 0, - statusBarHeight: this._layoutService.isVisible(Parts.STATUSBAR_PART) ? getTotalHeight(this._layoutService.getContainer(Parts.STATUSBAR_PART)) : 0, + titleBarHeight: this._layoutService.isVisible(Parts.TITLEBAR_PART) ? getTotalHeight(assertIsDefined(this._layoutService.getContainer(Parts.TITLEBAR_PART))) : 0, + activityBarWidth: this._layoutService.isVisible(Parts.ACTIVITYBAR_PART) ? getTotalWidth(assertIsDefined(this._layoutService.getContainer(Parts.ACTIVITYBAR_PART))) : 0, + sideBarWidth: this._layoutService.isVisible(Parts.SIDEBAR_PART) ? getTotalWidth(assertIsDefined(this._layoutService.getContainer(Parts.SIDEBAR_PART))) : 0, + statusBarHeight: this._layoutService.isVisible(Parts.STATUSBAR_PART) ? getTotalHeight(assertIsDefined(this._layoutService.getContainer(Parts.STATUSBAR_PART))) : 0, }; this._textFileService.write( URI.file(join(this._envService.userDataPath, 'rapid_render.json')), diff --git a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts index 77ff7a72859..ea28486ab26 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts @@ -25,6 +25,7 @@ import { DataTransfers } from 'vs/base/browser/dnd'; import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { assertIsDefined } from 'vs/base/common/types'; const FIND_FOCUS_CLASS = 'find-focused'; @@ -70,7 +71,8 @@ export class TerminalPanel extends Panel { this._attachEventListeners(this._parentDomElement, this._terminalContainer); - this._terminalService.setContainers(this.getContainer(), this._terminalContainer); + const container = assertIsDefined(this.getContainer()); + this._terminalService.setContainers(container, this._terminalContainer); this._register(this.themeService.onThemeChange(theme => this._updateTheme(theme))); this._register(this._configurationService.onDidChangeConfiguration(e => { diff --git a/src/vs/workbench/contrib/watermark/browser/watermark.ts b/src/vs/workbench/contrib/watermark/browser/watermark.ts index e9a4d74f213..e68c960a1f4 100644 --- a/src/vs/workbench/contrib/watermark/browser/watermark.ts +++ b/src/vs/workbench/contrib/watermark/browser/watermark.ts @@ -28,6 +28,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IDimension } from 'vs/platform/layout/browser/layoutService'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { assertIsDefined } from 'vs/base/common/types'; const $ = dom.$; @@ -122,7 +123,7 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr } private create(): void { - const container = this.layoutService.getContainer(Parts.EDITOR_PART); + const container = assertIsDefined(this.layoutService.getContainer(Parts.EDITOR_PART)); container.classList.add('has-watermark'); this.watermark = $('.watermark'); @@ -168,7 +169,9 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr this.watermark.remove(); const container = this.layoutService.getContainer(Parts.EDITOR_PART); - container.classList.remove('has-watermark'); + if (container) { + container.classList.remove('has-watermark'); + } this.watermarkDisposable.clear(); } diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index 77dbfb2c41a..b706a2d16a5 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -11,6 +11,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IWebviewService, Webview, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { Dimension } from 'vs/base/browser/dom'; +import { assertIsDefined } from 'vs/base/common/types'; /** * Webview editor overlay that creates and destroys the underlying webview as needed. @@ -48,7 +49,10 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd const container = document.createElement('div'); container.id = `webview-${this.id}`; container.style.visibility = 'hidden'; - this._layoutService.getContainer(Parts.EDITOR_PART).appendChild(container); + + const editorPart = assertIsDefined(this._layoutService.getContainer(Parts.EDITOR_PART)); + editorPart.appendChild(container); + return container; } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 42bf33c1191..1e7e3651884 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -50,7 +50,7 @@ import { IUpdateService } from 'vs/platform/update/common/update'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IPreferencesService } from '../services/preferences/common/preferences'; import { IMenubarService, IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/node/menubar'; -import { withNullAsUndefined } from 'vs/base/common/types'; +import { withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; import { IOpenerService, OpenOptions } from 'vs/platform/opener/common/opener'; import { Schemas } from 'vs/base/common/network'; import { IElectronService } from 'vs/platform/electron/node/electron'; @@ -253,7 +253,7 @@ export class ElectronWindow extends Disposable { // Maximize/Restore on doubleclick (for macOS custom title) if (isMacintosh && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { - const titlePart = this.layoutService.getContainer(Parts.TITLEBAR_PART); + const titlePart = assertIsDefined(this.layoutService.getContainer(Parts.TITLEBAR_PART)); this._register(DOM.addDisposableListener(titlePart, DOM.EventType.DBLCLICK, e => { DOM.EventHelper.stop(e); diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 6cccb046251..f0315cfc780 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -120,7 +120,7 @@ export class HistoryService extends Disposable implements IHistoryService { private lastEditLocation: IStackEntry | undefined; - private history: Array; + private history: Array = []; private recentlyClosedFiles: IRecentlyClosedFile[]; private loaded: boolean; private resourceFilter: ResourceGlobMatcher; diff --git a/src/vs/workbench/services/layout/browser/layoutService.ts b/src/vs/workbench/services/layout/browser/layoutService.ts index c17ec465ac6..0176b9ff57e 100644 --- a/src/vs/workbench/services/layout/browser/layoutService.ts +++ b/src/vs/workbench/services/layout/browser/layoutService.ts @@ -70,7 +70,7 @@ export interface IWorkbenchLayoutService extends ILayoutService { /** * Returns the parts HTML element, if there is one. */ - getContainer(part: Parts): HTMLElement; + getContainer(part: Parts): HTMLElement | undefined; /** * Returns if the part is visible. @@ -80,7 +80,7 @@ export interface IWorkbenchLayoutService extends ILayoutService { /** * Returns if the part is visible. */ - getDimension(part: Parts): Dimension; + getDimension(part: Parts): Dimension | undefined; /** * Set activity bar hidden or not diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 5d39163ccdb..b42e5d9fa73 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { guessMimeTypes } from 'vs/base/common/mime'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { URI } from 'vs/base/common/uri'; -import { isUndefinedOrNull } from 'vs/base/common/types'; +import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, ITextFileStreamContent, ILoadOptions, LoadReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; @@ -75,40 +75,34 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil private readonly _onDidStateChange: Emitter = this._register(new Emitter()); readonly onDidStateChange: Event = this._onDidStateChange.event; - private resource: URI; + private contentEncoding: string | undefined; // encoding as reported from disk - private contentEncoding: string; // encoding as reported from disk - private preferredEncoding: string | undefined; // encoding as chosen by the user + private versionId = 0; + private bufferSavedVersionId: number | undefined; + private blockModelContentChange = false; - private preferredMode: string | undefined; // mode as chosen by the user + private lastResolvedFileStat: IFileStatWithMetadata | undefined; - private versionId: number; - private bufferSavedVersionId: number; - private blockModelContentChange: boolean; - - private lastResolvedFileStat: IFileStatWithMetadata; - - private autoSaveAfterMillies?: number; - private autoSaveAfterMilliesEnabled: boolean; + private autoSaveAfterMillies: number | undefined; + private autoSaveAfterMilliesEnabled: boolean | undefined; private readonly autoSaveDisposable = this._register(new MutableDisposable()); - private saveSequentializer: SaveSequentializer; - private lastSaveAttemptTime: number; + private readonly saveSequentializer = new SaveSequentializer(); + private lastSaveAttemptTime = 0; - private contentChangeEventScheduler: RunOnceScheduler; - private orphanedChangeEventScheduler: RunOnceScheduler; + private readonly contentChangeEventScheduler = this._register(new RunOnceScheduler(() => this._onDidContentChange.fire(StateChange.CONTENT_CHANGE), TextFileEditorModel.DEFAULT_CONTENT_CHANGE_BUFFER_DELAY)); + private readonly orphanedChangeEventScheduler = this._register(new RunOnceScheduler(() => this._onDidStateChange.fire(StateChange.ORPHANED_CHANGE), TextFileEditorModel.DEFAULT_ORPHANED_CHANGE_BUFFER_DELAY)); - private dirty: boolean; - private inConflictMode: boolean; - private inOrphanMode: boolean; - private inErrorMode: boolean; - - private disposed: boolean; + private dirty = false; + private inConflictMode = false; + private inOrphanMode = false; + private inErrorMode = false; + private disposed = false; constructor( - resource: URI, - preferredEncoding: string | undefined, - preferredMode: string | undefined, + private resource: URI, + private preferredEncoding: string | undefined, // encoding as chosen by the user + private preferredMode: string | undefined, // mode as chosen by the user @INotificationService private readonly notificationService: INotificationService, @IModeService modeService: IModeService, @IModelService modelService: IModelService, @@ -123,18 +117,6 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ) { super(modelService, modeService); - this.resource = resource; - this.preferredEncoding = preferredEncoding; - this.preferredMode = preferredMode; - this.inOrphanMode = false; - this.dirty = false; - this.versionId = 0; - this.lastSaveAttemptTime = 0; - this.saveSequentializer = new SaveSequentializer(); - - this.contentChangeEventScheduler = this._register(new RunOnceScheduler(() => this._onDidContentChange.fire(StateChange.CONTENT_CHANGE), TextFileEditorModel.DEFAULT_CONTENT_CHANGE_BUFFER_DELAY)); - this.orphanedChangeEventScheduler = this._register(new RunOnceScheduler(() => this._onDidStateChange.fire(StateChange.ORPHANED_CHANGE), TextFileEditorModel.DEFAULT_ORPHANED_CHANGE_BUFFER_DELAY)); - this.updateAutoSaveConfiguration(textFileService.getAutoSaveConfiguration()); this.registerListeners(); @@ -727,12 +709,13 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Save to Disk // mark the save operation as currently pending with the versionId (it might have changed from a save participant triggering) this.logService.trace(`doSave(${versionId}) - before write()`, this.resource); - return this.saveSequentializer.setPending(newVersionId, this.textFileService.write(this.lastResolvedFileStat.resource, this.createSnapshot(), { + const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat); + return this.saveSequentializer.setPending(newVersionId, this.textFileService.write(lastResolvedFileStat.resource, this.createSnapshot(), { overwriteReadonly: options.overwriteReadonly, overwriteEncoding: options.overwriteEncoding, - mtime: this.lastResolvedFileStat.mtime, + mtime: lastResolvedFileStat.mtime, encoding: this.getEncoding(), - etag: this.lastResolvedFileStat.etag, + etag: lastResolvedFileStat.etag, writeElevated: options.writeElevated }).then(stat => { this.logService.trace(`doSave(${versionId}) - after write()`, this.resource); @@ -848,10 +831,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return Promise.resolve(); } - return this.saveSequentializer.setPending(versionId, this.textFileService.write(this.lastResolvedFileStat.resource, this.createSnapshot(), { - mtime: this.lastResolvedFileStat.mtime, + const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat); + return this.saveSequentializer.setPending(versionId, this.textFileService.write(lastResolvedFileStat.resource, this.createSnapshot(), { + mtime: lastResolvedFileStat.mtime, encoding: this.getEncoding(), - etag: this.lastResolvedFileStat.etag + etag: lastResolvedFileStat.etag }).then(stat => { // Updated resolved stat with updated stat since touching it might have changed mtime @@ -951,7 +935,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } } - getEncoding(): string { + getEncoding(): string | undefined { return this.preferredEncoding || this.contentEncoding; } @@ -1031,7 +1015,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return this.resource; } - getStat(): IFileStatWithMetadata { + getStat(): IFileStatWithMetadata | undefined { return this.lastResolvedFileStat; } diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts index 629e19c6b77..07c3271fa95 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts @@ -15,6 +15,7 @@ import { FileOperationResult, FileOperationError, IFileService } from 'vs/platfo import { IModelService } from 'vs/editor/common/services/modelService'; import { timeout } from 'vs/base/common/async'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; +import { assertIsDefined } from 'vs/base/common/types'; class ServiceAccessor { constructor(@ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService, @IFileService public fileService: TestFileService) { @@ -286,8 +287,8 @@ suite('Files - TextFileEditorModel', () => { model1.textEditorModel!.setValue('foo'); - const m1Mtime = model1.getStat().mtime; - const m2Mtime = model2.getStat().mtime; + const m1Mtime = assertIsDefined(model1.getStat()).mtime; + const m2Mtime = assertIsDefined(model2.getStat()).mtime; assert.ok(m1Mtime > 0); assert.ok(m2Mtime > 0); @@ -302,8 +303,8 @@ suite('Files - TextFileEditorModel', () => { await accessor.textFileService.saveAll(); assert.ok(!accessor.textFileService.isDirty(toResource.call(this, '/path/index_async.txt'))); assert.ok(!accessor.textFileService.isDirty(toResource.call(this, '/path/index_async2.txt'))); - assert.ok(model1.getStat().mtime > m1Mtime); - assert.ok(model2.getStat().mtime > m2Mtime); + assert.ok(assertIsDefined(model1.getStat()).mtime > m1Mtime); + assert.ok(assertIsDefined(model2.getStat()).mtime > m2Mtime); assert.ok(model1.getLastSaveAttemptTime() > m1Mtime); assert.ok(model2.getLastSaveAttemptTime() > m2Mtime); From 4fe8b82907bcd0e1dd88143d56acf7aca4267cd2 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 11:21:14 +0200 Subject: [PATCH 204/435] Fix customView.ts for strictFunctionTypes Part of #81574 --- src/vs/workbench/browser/parts/views/customView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 03c709a0e06..1b364d2784f 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -384,7 +384,7 @@ export class CustomTreeView extends Disposable implements ITreeView { const aligner = new Aligner(this.themeService); const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner); - this.tree = this._register(this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer], + this.tree = this._register(this.instantiationService.createInstance>(WorkbenchAsyncDataTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer], dataSource, { identityProvider: new CustomViewIdentityProvider(), accessibilityProvider: { From 3ba1fe28a03af2365393fb1feb28514622f26371 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 11:24:35 +0200 Subject: [PATCH 205/435] Revert "Fix customView.ts for strictFunctionTypes" This reverts commit 4fe8b82907bcd0e1dd88143d56acf7aca4267cd2. --- src/vs/workbench/browser/parts/views/customView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 1b364d2784f..03c709a0e06 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -384,7 +384,7 @@ export class CustomTreeView extends Disposable implements ITreeView { const aligner = new Aligner(this.themeService); const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner); - this.tree = this._register(this.instantiationService.createInstance>(WorkbenchAsyncDataTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer], + this.tree = this._register(this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer], dataSource, { identityProvider: new CustomViewIdentityProvider(), accessibilityProvider: { From 2b0a7df9dacc07490cc1938d1955316f3b796021 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 11:27:30 +0200 Subject: [PATCH 206/435] strict function types --- src/vs/platform/list/browser/listService.ts | 2 +- .../workbench/contrib/preferences/browser/keybindingsEditor.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index e3c42e0b054..e70bf539f65 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -430,7 +430,7 @@ export class WorkbenchTree extends Tree { constructor( container: HTMLElement, configuration: ITreeConfiguration, - options: ITreeOptions, + options: ITreeOptions | undefined, @IContextKeyService contextKeyService: IContextKeyService, @IListService listService: IListService, @IThemeService themeService: IThemeService, diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index 8d06fc22dcf..0437702abf9 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -29,7 +29,6 @@ import { } from 'vs/workbench/contrib/preferences/common/preferences'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; -import { List } from 'vs/base/browser/ui/list/listWidget'; import { IListVirtualDelegate, IListRenderer, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -79,7 +78,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor private keybindingsListContainer: HTMLElement; private unAssignedKeybindingItemToRevealAndFocus: IKeybindingItemEntry | null; private listEntries: IListEntry[]; - private keybindingsList: List; + private keybindingsList: WorkbenchList; private dimension: DOM.Dimension; private delayedFiltering: Delayer; From c1e90f3475cc6174cf8c0ffc908644a4b49d88f2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 7 Oct 2019 11:50:40 +0200 Subject: [PATCH 207/435] more strictPropertyInitialization related to #78168 --- src/vs/base/browser/ui/tree/objectTree.ts | 2 +- .../contrib/scm/browser/dirtydiffDecorator.ts | 12 ++++++------ src/vs/workbench/contrib/scm/browser/mainPanel.ts | 2 +- .../workbench/contrib/scm/browser/repositoryPanel.ts | 12 ++++++------ src/vs/workbench/contrib/scm/browser/scmViewlet.ts | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index eff86b6ab5e..be6082a4661 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -164,7 +164,7 @@ function asObjectTreeOptions(compressedTreeNodeProvider: () => I export class CompressibleObjectTree, TFilterData = void> extends ObjectTree implements ICompressedTreeNodeProvider { - protected model: CompressibleObjectTreeModel; + protected model!: CompressibleObjectTreeModel; constructor( user: string, diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index c7aec31036f..1eaf7d22cd0 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -163,11 +163,11 @@ function getOuterEditorFromDiffEditor(accessor: ServicesAccessor): ICodeEditor | class DirtyDiffWidget extends PeekViewWidget { - private diffEditor: EmbeddedDiffEditorWidget; + private diffEditor!: EmbeddedDiffEditorWidget; private title: string; private menu: IMenu; - private index: number; - private change: IChange; + private index: number = 0; + private change: IChange | undefined; private height: number | undefined = undefined; private contextKeyService: IContextKeyService; @@ -320,7 +320,7 @@ class DirtyDiffWidget extends PeekViewWidget { super._doLayoutBody(height, width); this.diffEditor.layout({ height, width }); - if (typeof this.height === 'undefined') { + if (typeof this.height === 'undefined' && this.change) { this.revealChange(this.change); } @@ -567,7 +567,7 @@ export class DirtyDiffController extends Disposable implements IEditorContributi private model: DirtyDiffModel | null = null; private widget: DirtyDiffWidget | null = null; private currentIndex: number = -1; - private readonly isDirtyDiffVisible: IContextKey; + private readonly isDirtyDiffVisible!: IContextKey; private session: IDisposable = Disposable.None; private mouseDownInfo: { lineNumber: number } | null = null; private enabled = false; @@ -953,7 +953,7 @@ function compareChanges(a: IChange, b: IChange): number { export class DirtyDiffModel extends Disposable { - private _originalModel: ITextModel | null; + private _originalModel: ITextModel | null = null; get original(): ITextModel | null { return this._originalModel; } get modified(): ITextModel | null { return this._editorModel; } diff --git a/src/vs/workbench/contrib/scm/browser/mainPanel.ts b/src/vs/workbench/contrib/scm/browser/mainPanel.ts index 4718b319830..2e0f160671a 100644 --- a/src/vs/workbench/contrib/scm/browser/mainPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/mainPanel.ts @@ -173,7 +173,7 @@ export class MainPanel extends ViewletPanel { static readonly ID = 'scm.mainPanel'; static readonly TITLE = localize('scm providers', "Source Control Providers"); - private list: List; + private list!: List; constructor( protected viewModel: IViewModel, diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index 55c19287d50..9566f4b1cba 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -525,12 +525,12 @@ export class RepositoryPanel extends ViewletPanel { private cachedHeight: number | undefined = undefined; private cachedWidth: number | undefined = undefined; - private inputBoxContainer: HTMLElement; - private inputBox: InputBox; - private listContainer: HTMLElement; - private tree: ObjectTree; - private viewModel: ViewModel; - private listLabels: ResourceLabels; + private inputBoxContainer!: HTMLElement; + private inputBox!: InputBox; + private listContainer!: HTMLElement; + private tree!: ObjectTree; + private viewModel!: ViewModel; + private listLabels!: ResourceLabels; private menus: SCMMenus; private toggleViewModelModeAction: ToggleViewModeAction | undefined; protected contextKeyService: IContextKeyService; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts index 4ce397b202f..a4207212fd4 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts @@ -54,7 +54,7 @@ export class SCMViewlet extends ViewContainerViewlet implements IViewModel { private static readonly STATE_KEY = 'workbench.scm.views.state'; - private el: HTMLElement; + private el!: HTMLElement; private message: HTMLElement; private menus: SCMMenus; private _repositories: ISCMRepository[] = []; From 0cfba55686b4ec6ea9763f56180a83fa5a29669c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 11:56:15 +0200 Subject: [PATCH 208/435] add enableInspectPort-method which uses sigusr1/_debugProcess --- .../electron-browser/extensionHost.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 1963444f46f..45428fe5995 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -45,6 +45,8 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { private readonly _onExit: Emitter<[number, string]> = new Emitter<[number, string]>(); public readonly onExit: Event<[number, string]> = this._onExit.event; + private readonly _onDidSetInspectPort = new Emitter(); + private readonly _toDispose = new DisposableStore(); private readonly _isExtensionDevHost: boolean; @@ -198,6 +200,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { } if (!this._inspectPort) { this._inspectPort = Number(inspectorUrlMatch[2]); + this._onDidSetInspectPort.fire(); } } else { console.group('Extension Host'); @@ -223,6 +226,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portData.actual); } this._inspectPort = portData.actual; + this._onDidSetInspectPort.fire(); } // Help in case we fail to start it @@ -466,6 +470,37 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { this._onExit.fire([code, signal]); } + public async enableInspectPort(): Promise { + if (typeof this._inspectPort === 'number') { + return true; + } + + if (!this._extensionHostProcess) { + return false; + } + + interface ProcessExt { + _debugProcess?(n: number): any; + } + + if (typeof (process)._debugProcess === 'function') { + // use (undocumented) _debugProcess feature of node + (process)._debugProcess!(this._extensionHostProcess.pid); + await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]); + return typeof this._inspectPort === 'number'; + + } else if (!platform.isWindows) { + // use KILL USR1 on non-windows platforms (fallback) + this._extensionHostProcess.kill('SIGUSR1'); + await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]); + return typeof this._inspectPort === 'number'; + + } else { + // not supported... + return false; + } + } + public getInspectPort(): number | undefined { return withNullAsUndefined(this._inspectPort); } From d82755c6507af684f6a2d3029e8f0049d181b096 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 12:05:00 +0200 Subject: [PATCH 209/435] remove used method --- .../services/extensions/common/extensionHostProcessManager.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts index 3aff4a5e57f..7bcf574d9ed 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts @@ -248,10 +248,6 @@ export class ExtensionHostProcessManager extends Disposable { return 0; } - public canProfileExtensionHost(): boolean { - return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort()); - } - public async resolveAuthority(remoteAuthority: string): Promise { const authorityPlusIndex = remoteAuthority.indexOf('+'); if (authorityPlusIndex === -1) { From 32b4eb7359fcec4b5beb19dc1c469c8cb2efefe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D4=9C=D0=B5=D1=95?= <5124946+wesinator@users.noreply.github.com> Date: Mon, 7 Oct 2019 06:08:52 -0400 Subject: [PATCH 210/435] Add .har extension to JSON language (#77300) --- extensions/json/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/json/package.json b/extensions/json/package.json index 6ef4b971691..e66955770bc 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -27,7 +27,8 @@ ".swcrc", ".webmanifest", ".js.map", - ".css.map" + ".css.map", + ".har" ], "filenames": [ "composer.lock", From 2ca00003a6aa0ab1772902e857bfad28a0ab2460 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 12:15:16 +0200 Subject: [PATCH 211/435] expose `enableInspectPort` in starter type --- .../extensions/browser/webWorkerExtensionHostStarter.ts | 4 ++++ src/vs/workbench/services/extensions/common/extensions.ts | 1 + .../services/extensions/common/remoteExtensionHostClient.ts | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHostStarter.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHostStarter.ts index 406331cb2bc..e74228ce1dc 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHostStarter.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHostStarter.ts @@ -113,6 +113,10 @@ export class WebWorkerExtensionHostStarter implements IExtensionHostStarter { return undefined; } + enableInspectPort(): Promise { + return Promise.resolve(false); + } + private async _createExtHostInitData(): Promise { const [telemetryInfo, extensionDescriptions] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._extensions]); const workspace = this._contextService.getWorkspace(); diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index d68777ae83b..0a436b45858 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -89,6 +89,7 @@ export interface IExtensionHostStarter { start(): Promise | null; getInspectPort(): number | undefined; + enableInspectPort(): Promise; dispose(): void; } diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts index 8dfa1bd4522..83b800cad49 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts @@ -225,6 +225,10 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH return undefined; } + enableInspectPort(): Promise { + return Promise.resolve(false); + } + dispose(): void { super.dispose(); From 0f2cda10da1e80088ad7908ac0f743c8f2132de0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 12:22:16 +0200 Subject: [PATCH 212/435] support to enable inspector when asking for inspect port and consume in auto extension profiler --- .../extensions/electron-browser/extensionProfileService.ts | 4 ++-- .../extensions/electron-browser/extensionsAutoProfiler.ts | 2 +- .../extensions/electron-browser/runtimeExtensionsEditor.ts | 2 +- .../services/extensions/common/abstractExtensionService.ts | 4 ++-- .../extensions/common/extensionHostProcessManager.ts | 5 ++++- src/vs/workbench/services/extensions/common/extensions.ts | 4 ++-- .../services/extensions/electron-browser/extensionService.ts | 4 ++-- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts index 79f86a33774..29ae1fd3043 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts @@ -107,12 +107,12 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio } } - public startProfiling(): Promise | null { + public async startProfiling(): Promise { if (this._state !== ProfileSessionState.None) { return null; } - const inspectPort = this._extensionService.getInspectPort(); + const inspectPort = await this._extensionService.getInspectPort(false); if (!inspectPort) { return this._dialogService.confirm({ type: 'info', diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts index 56fe69484cd..c5b6f8b87a1 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts @@ -43,7 +43,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont private async _onDidChangeResponsiveChange(event: IResponsiveStateChangeEvent): Promise { - const port = this._extensionService.getInspectPort(); + const port = await this._extensionService.getInspectPort(true); if (!port) { return; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index ffe0daa5e1c..54e11fc1507 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -547,7 +547,7 @@ export class DebugExtensionHostAction extends Action { async run(): Promise { - const inspectPort = this._extensionService.getInspectPort(); + const inspectPort = await this._extensionService.getInspectPort(false); if (!inspectPort) { const res = await this._dialogService.confirm({ type: 'info', diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 65d4c2f70ac..c67415584ef 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -256,8 +256,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return result; } - public getInspectPort(): number { - return 0; + public getInspectPort(_tryEnableInspector: boolean): Promise { + return Promise.resolve(0); } public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { diff --git a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts index 7bcf574d9ed..746953e1d39 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts @@ -238,8 +238,11 @@ export class ExtensionHostProcessManager extends Disposable { }); } - public getInspectPort(): number { + public async getInspectPort(tryEnableInspector: boolean): Promise { if (this._extensionHostProcessWorker) { + if (tryEnableInspector) { + await this._extensionHostProcessWorker.enableInspectPort(); + } let port = this._extensionHostProcessWorker.getInspectPort(); if (port) { return port; diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 0a436b45858..074447cab22 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -213,7 +213,7 @@ export interface IExtensionService { * Return the inspect port or `0`, the latter means inspection * is not possible. */ - getInspectPort(): number; + getInspectPort(tryEnableInspector: boolean): Promise; /** * Restarts the extension host. @@ -271,7 +271,7 @@ export class NullExtensionService implements IExtensionService { getExtension() { return Promise.resolve(undefined); } readExtensionPointContributions(_extPoint: IExtensionPoint): Promise[]> { return Promise.resolve(Object.create(null)); } getExtensionsStatus(): { [id: string]: IExtensionsStatus; } { return Object.create(null); } - getInspectPort(): number { return 0; } + getInspectPort(_tryEnableInspector: boolean): Promise { return Promise.resolve(0); } restartExtensionHost(): void { } async setRemoteEnvironment(_env: { [key: string]: string | null }): Promise { } canAddExtension(): boolean { return false; } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 9cc156d3d11..6387493212b 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -537,9 +537,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions()); } - public getInspectPort(): number { + public async getInspectPort(tryEnableInspector: boolean): Promise { if (this._extensionHostProcessManagers.length > 0) { - return this._extensionHostProcessManagers[0].getInspectPort(); + return this._extensionHostProcessManagers[0].getInspectPort(tryEnableInspector); } return 0; } From 84786d378c7e9d558a1dffc5fa7ee45b8ee8b6dc Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 7 Oct 2019 12:39:34 +0200 Subject: [PATCH 213/435] distro fixes #81919 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 275623fa18b..fbeb6d1e659 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "b9bb6392c20ba05a247e41ea75b2825544fd8afd", + "distro": "fd32ba99f225d591cb667f0bdf23dbb481743eab", "author": { "name": "Microsoft Corporation" }, @@ -153,4 +153,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +} \ No newline at end of file From 2d96b9b616db2570ff5db1d918358a17bd91ada3 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 12:41:19 +0200 Subject: [PATCH 214/435] Fix global tasks again Fixes https://github.com/microsoft/vscode/issues/78817 --- src/vs/workbench/api/browser/mainThreadTask.ts | 2 +- .../contrib/tasks/browser/abstractTaskService.ts | 7 ++++++- .../contrib/tasks/browser/terminalTaskSystem.ts | 9 ++++++++- src/vs/workbench/contrib/tasks/common/tasks.ts | 4 ++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTask.ts b/src/vs/workbench/api/browser/mainThreadTask.ts index 9e5763d0614..e904b50d182 100644 --- a/src/vs/workbench/api/browser/mainThreadTask.ts +++ b/src/vs/workbench/api/browser/mainThreadTask.ts @@ -264,7 +264,7 @@ namespace TaskSourceDTO { } } else if (value.kind === TaskSourceKind.Workspace) { result.extensionId = '$core'; - result.scope = value.config.workspaceFolder.uri; + result.scope = value.config.workspaceFolder ? value.config.workspaceFolder.uri : TaskScope.Global; } return result; } diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 23fbb2cbd15..6a3efa5fd4b 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -983,7 +983,12 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private getResourceForTask(task: CustomTask): URI { let uri = this.getResourceForKind(task._source.kind); if (!uri) { - uri = task.getWorkspaceFolder().toResource(task._source.config.file); + const taskFolder = task.getWorkspaceFolder(); + if (taskFolder) { + uri = taskFolder.toResource(task._source.config.file); + } else { + uri = this.workspaceFolders[0].uri; + } } return uri; } diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index ce5593930c6..1c45953acdf 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -462,7 +462,14 @@ export class TerminalTaskSystem implements ITaskSystem { } private executeCommand(task: CustomTask | ContributedTask, trigger: string): Promise { - const workspaceFolder = this.currentTask.workspaceFolder = task.getWorkspaceFolder(); + const taskWorkspaceFolder = task.getWorkspaceFolder(); + let workspaceFolder: IWorkspaceFolder | undefined; + if (taskWorkspaceFolder) { + workspaceFolder = this.currentTask.workspaceFolder = taskWorkspaceFolder; + } else { + const folders = this.contextService.getWorkspace().folders; + workspaceFolder = folders.length > 0 ? folders[0] : undefined; + } const systemInfo: TaskSystemInfo | undefined = this.currentTask.systemInfo = workspaceFolder ? this.taskSystemInfoResolver(workspaceFolder) : undefined; let variables = new Set(); diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 0737e5fea02..760c3f67664 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -380,7 +380,7 @@ export namespace TaskSourceKind { } export interface TaskSourceConfigElement { - workspaceFolder: IWorkspaceFolder; + workspaceFolder?: IWorkspaceFolder; workspace?: IWorkspace; file: string; index: number; @@ -728,7 +728,7 @@ export class CustomTask extends CommonTask { return JSON.stringify(key); } - public getWorkspaceFolder(): IWorkspaceFolder { + public getWorkspaceFolder(): IWorkspaceFolder | undefined { return this._source.config.workspaceFolder; } From 5fe0604806c04f58cf2f0cf7cdb7011fba7e0095 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 13:05:51 +0200 Subject: [PATCH 215/435] enable strictFunctionTypes #81574 --- src/vs/workbench/contrib/debug/browser/breakpointWidget.ts | 7 +++++-- src/vs/workbench/contrib/debug/browser/debugSession.ts | 2 +- src/vs/workbench/contrib/debug/common/debug.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts index 3ba18b6a7f0..dee135687c4 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts @@ -54,8 +54,9 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi private hitCountInput = ''; private logMessageInput = ''; private breakpoint: IBreakpoint | undefined; + private context: Context; - constructor(editor: ICodeEditor, private lineNumber: number, private column: number | undefined, private context: Context, + constructor(editor: ICodeEditor, private lineNumber: number, private column: number | undefined, context: Context | undefined, @IContextViewService private readonly contextViewService: IContextViewService, @IDebugService private readonly debugService: IDebugService, @IThemeService private readonly themeService: IThemeService, @@ -74,7 +75,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi this.breakpoint = breakpoints.length ? breakpoints[0] : undefined; } - if (this.context === undefined) { + if (context === undefined) { if (this.breakpoint && !this.breakpoint.condition && !this.breakpoint.hitCondition && this.breakpoint.logMessage) { this.context = Context.LOG_MESSAGE; } else if (this.breakpoint && !this.breakpoint.condition && this.breakpoint.hitCondition) { @@ -82,6 +83,8 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi } else { this.context = Context.CONDITION; } + } else { + this.context = context; } this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(e => { diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index dcedf0a95e2..fcec6934cfb 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -65,7 +65,7 @@ export class DebugSession implements IDebugSession { constructor( private _configuration: { resolved: IConfig, unresolved: IConfig | undefined }, - public root: IWorkspaceFolder, + public root: IWorkspaceFolder | undefined, private model: DebugModel, options: IDebugSessionOptions | undefined, @IDebugService private readonly debugService: IDebugService, diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 81e4d032dba..c68bc35d6ab 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -160,7 +160,7 @@ export interface IDebugSession extends ITreeElement { readonly configuration: IConfig; readonly unresolvedConfiguration: IConfig | undefined; readonly state: State; - readonly root: IWorkspaceFolder; + readonly root: IWorkspaceFolder | undefined; readonly parentSession: IDebugSession | undefined; readonly subId: string | undefined; From 28402eb95661a631e85fd115eeae95f1fd91f419 Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Mon, 7 Oct 2019 04:58:48 -0700 Subject: [PATCH 216/435] Update sql language syntax (#77601) * update sql language syntax * Remove changes to sql grammar --- extensions/sql/language-configuration.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/sql/language-configuration.json b/extensions/sql/language-configuration.json index a9c154bcec8..cf96472ffd8 100644 --- a/extensions/sql/language-configuration.json +++ b/extensions/sql/language-configuration.json @@ -12,8 +12,9 @@ ["{", "}"], ["[", "]"], ["(", ")"], - ["\"", "\""], - ["'", "'"] + { "open": "\"", "close": "\"", "notIn": ["string"] }, + { "open": "N'", "close": "'", "notIn": ["string", "comment"] }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] } ], "surroundingPairs": [ ["{", "}"], From d212bf7c0bd6eeced7f79be16bc6e8fe6d06aa57 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 14:07:17 +0200 Subject: [PATCH 217/435] simplify find port, remote hacky env variables --- .../contrib/debug/node/debugAdapter.ts | 1 - .../electron-browser/extensionHost.ts | 69 +++++++++---------- .../node/extensionHostProcessSetup.ts | 14 ---- 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index 84ec75a9c84..617c0fa74d3 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -178,7 +178,6 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { if (options.env) { env = objects.mixin(env, options.env); } - delete env.VSCODE_PREVENT_FOREIGN_INSPECT; if (command === 'node') { if (Array.isArray(args) && args.length > 0) { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 45428fe5995..4f2ad4af23b 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -16,7 +16,7 @@ import * as platform from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { IRemoteConsoleLog, log } from 'vs/base/common/console'; import { logRemoteEntry } from 'vs/workbench/services/extensions/common/remoteConsoleUtil'; -import { findFreePort, randomPort } from 'vs/base/node/ports'; +import { findFreePort } from 'vs/base/node/ports'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net'; import { generateRandomPipeName, NodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; @@ -129,10 +129,10 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { if (!this._messageProtocol) { this._messageProtocol = Promise.all([ this._tryListenOnPipe(), - !this._environmentService.args['disable-inspect'] ? this._tryFindDebugPort() : Promise.resolve(null) + !this._environmentService.args['disable-inspect'] ? this._tryFindDebugPort() : 0 ]).then(data => { const pipeName = data[0]; - const portData = data[1]; + const portNumber = data[1]; const opts = { env: objects.mixin(objects.deepClone(process.env), { @@ -153,16 +153,11 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { silent: true }; - if (portData && portData.actual) { + if (portNumber !== 0) { opts.execArgv = [ '--nolazy', - (this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portData.actual + (this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portNumber ]; - if (!portData.expected) { - // No one asked for 'inspect' or 'inspect-brk', only us. We add another - // option such that the extension host can manipulate the execArgv array - opts.env.VSCODE_PREVENT_FOREIGN_INSPECT = true; - } } const crashReporterOptions = undefined; // TODO@electron pass this in as options to the extension host after verifying this actually works @@ -221,11 +216,11 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { this._extensionHostProcess.on('exit', (code: number, signal: string) => this._onExtHostProcessExit(code, signal)); // Notify debugger that we are ready to attach to the process if we run a development extension - if (portData) { - if (this._isExtensionDevHost && portData.actual && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) { - this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portData.actual); + if (portNumber) { + if (this._isExtensionDevHost && portNumber && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) { + this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portNumber); } - this._inspectPort = portData.actual; + this._inspectPort = portNumber; this._onDidSetInspectPort.fire(); } @@ -279,29 +274,31 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { /** * Find a free port if extension host debugging is enabled. */ - private _tryFindDebugPort(): Promise<{ expected: number; actual: number }> { - let expected: number; - let startPort = randomPort(); - if (typeof this._environmentService.debugExtensionHost.port === 'number') { - startPort = expected = this._environmentService.debugExtensionHost.port; + private async _tryFindDebugPort(): Promise { + + if (typeof this._environmentService.debugExtensionHost.port !== 'number') { + return 0; } - return new Promise(resolve => { - return findFreePort(startPort, 10 /* try 10 ports */, 5000 /* try up to 5 seconds */).then(port => { - if (!port) { - console.warn('%c[Extension Host] %cCould not find a free port for debugging', 'color: blue', 'color:'); - } else { - if (expected && port !== expected) { - console.warn(`%c[Extension Host] %cProvided debugging port ${expected} is not free, using ${port} instead.`, 'color: blue', 'color:'); - } - if (this._isExtensionDevDebugBrk) { - console.warn(`%c[Extension Host] %cSTOPPED on first line for debugging on port ${port}`, 'color: blue', 'color:'); - } else { - console.info(`%c[Extension Host] %cdebugger listening on port ${port}`, 'color: blue', 'color:'); - } - } - return resolve({ expected, actual: port }); - }); - }); + + const expected = this._environmentService.debugExtensionHost.port; + const port = await findFreePort(expected, 10 /* try 10 ports */, 5000 /* try up to 5 seconds */); + + if (!port) { + console.warn('%c[Extension Host] %cCould not find a free port for debugging', 'color: blue', 'color:'); + return 0; + } + + if (port !== expected) { + console.warn(`%c[Extension Host] %cProvided debugging port ${expected} is not free, using ${port} instead.`, 'color: blue', 'color:'); + } + if (this._isExtensionDevDebugBrk) { + console.warn(`%c[Extension Host] %cSTOPPED on first line for debugging on port ${port}`, 'color: blue', 'color:'); + } else { + console.info(`%c[Extension Host] %cdebugger listening on port ${port}`, 'color: blue', 'color:'); + } + return port; + + } private _tryExtHostHandshake(): Promise { diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts index 9f5a14f6cb0..bbd3b8e3ef5 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -275,20 +275,6 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise { const protocol = await createExtHostProtocol(); From 5d413d741880fc464db1e8a93ce98521d5f6d7ab Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 14:09:05 +0200 Subject: [PATCH 218/435] remove --disable-inspect --- scripts/test-integration.bat | 8 ++++---- scripts/test-integration.sh | 10 +++++----- src/vs/platform/environment/common/environment.ts | 1 - src/vs/platform/environment/node/argv.ts | 1 - .../extensions/electron-browser/extensionHost.ts | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index d557a24edaa..8de32c95a0f 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -29,16 +29,16 @@ call .\scripts\test.bat --runGlob **\*.integrationTest.js %* if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in the extension host -call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% . +call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% . if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in commonJS (HTML, CSS, JSON language server tests...) diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index df6219221b7..04ffdf64e3c 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -37,13 +37,13 @@ fi ./scripts/test.sh --runGlob **/*.integrationTest.js "$@" # Tests in the extension host -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR mkdir -p $ROOT/extensions/emmet/test-fixtures -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR rm -rf $ROOT/extensions/emmet/test-fixtures # Remote Integration Tests diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 789bb4c805f..f24dd80b347 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -71,7 +71,6 @@ export interface ParsedArgs { 'driver-verbose'?: boolean; remote?: string; 'disable-user-env-probe'?: boolean; - 'disable-inspect'?: boolean; 'force'?: boolean; 'force-user-env'?: boolean; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index e61113171d0..c15320d20b1 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -109,7 +109,6 @@ export const OPTIONS: OptionDescriptions> = { 'trace': { type: 'boolean' }, 'trace-category-filter': { type: 'string' }, 'trace-options': { type: 'string' }, - 'disable-inspect': { type: 'boolean' }, 'force-user-env': { type: 'boolean' }, 'js-flags': { type: 'string' }, // chrome js flags diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 4f2ad4af23b..b7ac24ab84a 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -129,7 +129,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { if (!this._messageProtocol) { this._messageProtocol = Promise.all([ this._tryListenOnPipe(), - !this._environmentService.args['disable-inspect'] ? this._tryFindDebugPort() : 0 + this._tryFindDebugPort() ]).then(data => { const pipeName = data[0]; const portNumber = data[1]; From 32b28614984c4decfaa59760303e24f9ac548e95 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Oct 2019 14:17:39 +0200 Subject: [PATCH 219/435] workaround - remove `as const` to make webpack happy... --- extensions/markdown-language-features/src/util/links.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-language-features/src/util/links.ts b/extensions/markdown-language-features/src/util/links.ts index 19c8627d49f..cb3228cc8be 100644 --- a/extensions/markdown-language-features/src/util/links.ts +++ b/extensions/markdown-language-features/src/util/links.ts @@ -14,12 +14,12 @@ export const Schemes = { vscode: 'vscode:', 'vscode-insiders': 'vscode-insiders:', 'vscode-resource': 'vscode-resource', -} as const; +}; const knownSchemes = [ ...Object.values(Schemes), `${vscode.env.uriScheme}:` -] as const; +]; export function getUriForLinkWithKnownExternalScheme(link: string): vscode.Uri | undefined { if (knownSchemes.some(knownScheme => isOfScheme(knownScheme, link))) { From 56087d67e35e61a0eb249b00606d89d870138ded Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 14:17:53 +0200 Subject: [PATCH 220/435] debt - strict function --- .../parts/quickopen/browser/quickOpenModel.ts | 10 +-- .../parts/activitybar/activitybarActions.ts | 10 ++- .../parts/activitybar/activitybarPart.ts | 2 +- .../browser/parts/compositeBarActions.ts | 2 +- .../browser/parts/panel/panelPart.ts | 4 +- .../quickopen/browser/commandsHandler.ts | 62 +++++++++---------- .../quickopen/browser/gotoSymbolHandler.ts | 2 +- .../contrib/scm/browser/mainPanel.ts | 3 +- .../search/browser/openSymbolHandler.ts | 2 +- 9 files changed, 50 insertions(+), 47 deletions(-) diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts index fdd8bcbf06b..5e1b2154cc1 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts @@ -53,7 +53,7 @@ export const QuickOpenItemAccessor = new QuickOpenItemAccessorClass(); export class QuickOpenEntry { private id: string; - private labelHighlights: IHighlight[]; + private labelHighlights?: IHighlight[]; private descriptionHighlights?: IHighlight[]; private detailHighlights?: IHighlight[]; private hidden: boolean | undefined; @@ -160,7 +160,7 @@ export class QuickOpenEntry { /** * Allows to set highlight ranges that should show up for the entry label and optionally description if set. */ - setHighlights(labelHighlights: IHighlight[], descriptionHighlights?: IHighlight[], detailHighlights?: IHighlight[]): void { + setHighlights(labelHighlights?: IHighlight[], descriptionHighlights?: IHighlight[], detailHighlights?: IHighlight[]): void { this.labelHighlights = labelHighlights; this.descriptionHighlights = descriptionHighlights; this.detailHighlights = detailHighlights; @@ -169,7 +169,7 @@ export class QuickOpenEntry { /** * Allows to return highlight ranges that should show up for the entry label and description. */ - getHighlights(): [IHighlight[] /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] { + getHighlights(): [IHighlight[] | undefined /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] { return [this.labelHighlights, this.descriptionHighlights, this.detailHighlights]; } @@ -260,7 +260,7 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { return this.entry; } - getHighlights(): [IHighlight[], IHighlight[] | undefined, IHighlight[] | undefined] { + getHighlights(): [IHighlight[] | undefined, IHighlight[] | undefined, IHighlight[] | undefined] { return this.entry ? this.entry.getHighlights() : super.getHighlights(); } @@ -268,7 +268,7 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { return this.entry ? this.entry.isHidden() : super.isHidden(); } - setHighlights(labelHighlights: IHighlight[], descriptionHighlights?: IHighlight[], detailHighlights?: IHighlight[]): void { + setHighlights(labelHighlights?: IHighlight[], descriptionHighlights?: IHighlight[], detailHighlights?: IHighlight[]): void { this.entry ? this.entry.setHighlights(labelHighlights, descriptionHighlights, detailHighlights) : super.setHighlights(labelHighlights, descriptionHighlights, detailHighlights); } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 4757e8efca6..a4824f6c7b6 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -163,15 +163,19 @@ export class GlobalActivityActionViewItem extends ActivityActionViewItem { export class PlaceHolderViewletActivityAction extends ViewletActivityAction { constructor( - id: string, name: string, iconUrl: URI, + id: string, + name: string, + iconUrl: URI | undefined, @IViewletService viewletService: IViewletService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @ITelemetryService telemetryService: ITelemetryService ) { super({ id, name: id, cssClass: `extensionViewlet-placeholder-${id.replace(/\./g, '-')}` }, viewletService, layoutService, telemetryService); - const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar - DOM.createCSSRule(iconClass, `-webkit-mask: ${DOM.asCSSUrl(iconUrl)} no-repeat 50% 50%; -webkit-mask-size: 24px;`); + if (iconUrl) { + const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar + DOM.createCSSRule(iconClass, `-webkit-mask: ${DOM.asCSSUrl(iconUrl)} no-repeat 50% 50%; -webkit-mask-size: 24px;`); + } } setActivity(activity: IActivity): void { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index f45b3f776f4..416d5f00da5 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -110,7 +110,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true), getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction, getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction, - getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), + getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, assertIsDefined(this.viewletService.getViewlet(compositeId))), getContextMenuActions: () => [this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))], getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), hidePart: () => this.layoutService.setSideBarHidden(true), diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 7485e7a8658..f59e024ded1 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -439,7 +439,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { constructor( private compositeActivityAction: ActivityAction, private toggleCompositePinnedAction: Action, - private contextMenuActionsProvider: () => Action[], + private contextMenuActionsProvider: () => ReadonlyArray, colors: (theme: ITheme) => ICompositeBarColors, icon: boolean, private compositeBar: ICompositeBar, diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index bfec292330a..c134e3b8d3a 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -123,7 +123,7 @@ export class PanelPart extends CompositePart implements IPanelService { openComposite: (compositeId: string) => Promise.resolve(this.openPanel(compositeId, true)), getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction, getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction, - getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), + getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))), getContextMenuActions: () => [ this.instantiationService.createInstance(TogglePanelPositionAction, TogglePanelPositionAction.ID, TogglePanelPositionAction.LABEL), this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel")) @@ -330,7 +330,7 @@ export class PanelPart extends CompositePart implements IPanelService { let compositeActions = this.compositeActions.get(compositeId); if (!compositeActions) { compositeActions = { - activityAction: this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), + activityAction: this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))), pinnedAction: new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar) }; diff --git a/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts b/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts index a0090bae844..334b144c0db 100644 --- a/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; -import * as arrays from 'vs/base/common/arrays'; -import * as types from 'vs/base/common/types'; +import { localize } from 'vs/nls'; +import { distinct } from 'vs/base/common/arrays'; +import { withNullAsUndefined, isFunction } from 'vs/base/common/types'; import { Language } from 'vs/base/common/platform'; import { Action, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen'; @@ -137,7 +137,7 @@ class CommandsHistory extends Disposable { export class ShowAllCommandsAction extends Action { static readonly ID = 'workbench.action.showCommands'; - static readonly LABEL = nls.localize('showTriggerActions', "Show All Commands"); + static readonly LABEL = localize('showTriggerActions', "Show All Commands"); constructor( id: string, @@ -167,7 +167,7 @@ export class ShowAllCommandsAction extends Action { export class ClearCommandHistoryAction extends Action { static readonly ID = 'workbench.action.clearCommandHistory'; - static readonly LABEL = nls.localize('clearCommandHistory', "Clear Command History"); + static readonly LABEL = localize('clearCommandHistory', "Clear Command History"); constructor( id: string, @@ -196,7 +196,7 @@ class CommandPaletteEditorAction extends EditorAction { constructor() { super({ id: ShowAllCommandsAction.ID, - label: nls.localize('showCommands.label', "Command Palette..."), + label: localize('showCommands.label', "Command Palette..."), alias: 'Command Palette', precondition: undefined, menuOpts: { @@ -224,10 +224,10 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { constructor( private commandId: string, - private keybinding: ResolvedKeybinding, + private keybinding: ResolvedKeybinding | undefined, private label: string, - alias: string, - highlights: { label: IHighlight[], alias?: IHighlight[] }, + alias: string | undefined, + highlights: { label: IHighlight[] | null, alias: IHighlight[] | null }, private onBeforeRun: (commandId: string) => void, @INotificationService private readonly notificationService: INotificationService, @ITelemetryService protected telemetryService: ITelemetryService @@ -240,10 +240,10 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { if (this.label !== alias) { this.alias = alias; } else { - highlights.alias = undefined; + highlights.alias = null; } - this.setHighlights(highlights.label, undefined, highlights.alias); + this.setHighlights(withNullAsUndefined(highlights.label), undefined, withNullAsUndefined(highlights.alias)); } getCommandId(): string { @@ -266,7 +266,7 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { this.description = description; } - getKeybinding(): ResolvedKeybinding { + getKeybinding(): ResolvedKeybinding | undefined { return this.keybinding; } @@ -276,10 +276,10 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { getAriaLabel(): string { if (this.keybindingAriaLabel) { - return nls.localize('entryAriaLabelWithKey', "{0}, {1}, commands", this.getLabel(), this.keybindingAriaLabel); + return localize('entryAriaLabelWithKey', "{0}, {1}, commands", this.getLabel(), this.keybindingAriaLabel); } - return nls.localize('entryAriaLabel', "{0}, commands", this.getLabel()); + return localize('entryAriaLabel', "{0}, commands", this.getLabel()); } run(mode: Mode, context: IEntryRunContext): boolean { @@ -319,7 +319,7 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { this.onError(error); } } else { - this.notificationService.info(nls.localize('actionNotEnabled', "Command '{0}' is not enabled in the current context.", this.getLabel())); + this.notificationService.info(localize('actionNotEnabled', "Command '{0}' is not enabled in the current context.", this.getLabel())); } }, 50); } @@ -329,7 +329,7 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup { return; } - this.notificationService.error(error || nls.localize('canNotRun', "Command '{0}' resulted in an error.", this.label)); + this.notificationService.error(error || localize('canNotRun', "Command '{0}' resulted in an error.", this.label)); } } @@ -337,10 +337,10 @@ class EditorActionCommandEntry extends BaseCommandEntry { constructor( commandId: string, - keybinding: ResolvedKeybinding, + keybinding: ResolvedKeybinding | undefined, label: string, - meta: string, - highlights: { label: IHighlight[], alias: IHighlight[] }, + meta: string | undefined, + highlights: { label: IHighlight[] | null, alias: IHighlight[] | null }, private action: IEditorAction, onBeforeRun: (commandId: string) => void, @INotificationService notificationService: INotificationService, @@ -358,10 +358,10 @@ class ActionCommandEntry extends BaseCommandEntry { constructor( commandId: string, - keybinding: ResolvedKeybinding, + keybinding: ResolvedKeybinding | undefined, label: string, - alias: string, - highlights: { label: IHighlight[], alias: IHighlight[] }, + alias: string | undefined, + highlights: { label: IHighlight[] | null, alias: IHighlight[] | null }, private action: Action, onBeforeRun: (commandId: string) => void, @INotificationService notificationService: INotificationService, @@ -439,7 +439,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { // Editor Actions const activeTextEditorWidget = this.editorService.activeTextEditorWidget; let editorActions: IEditorAction[] = []; - if (activeTextEditorWidget && types.isFunction(activeTextEditorWidget.getSupportedActions)) { + if (activeTextEditorWidget && isFunction(activeTextEditorWidget.getSupportedActions)) { editorActions = activeTextEditorWidget.getSupportedActions(); } @@ -456,7 +456,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { let entries = [...editorEntries, ...commandEntries]; // Remove duplicates - entries = arrays.distinct(entries, entry => `${entry.getLabel()}${entry.getGroupLabel()}${entry.getCommandId()}`); + entries = distinct(entries, entry => `${entry.getLabel()}${entry.getGroupLabel()}${entry.getCommandId()}`); // Handle label clashes const commandLabels = new Set(); @@ -494,12 +494,12 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { // only if we have recently used commands in the result set const firstEntry = entries[0]; if (firstEntry && this.commandsHistory.peek(firstEntry.getCommandId())) { - firstEntry.setGroupLabel(nls.localize('recentlyUsed', "recently used")); + firstEntry.setGroupLabel(localize('recentlyUsed', "recently used")); for (let i = 1; i < entries.length; i++) { const entry = entries[i]; if (!this.commandsHistory.peek(entry.getCommandId())) { entry.setShowBorder(true); - entry.setGroupLabel(nls.localize('morecCommands', "other commands")); + entry.setGroupLabel(localize('morecCommands', "other commands")); break; } } @@ -520,7 +520,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { if (label) { // Alias for non default languages - const alias = !Language.isDefaultVariant() ? action.alias : null; + const alias = !Language.isDefaultVariant() ? action.alias : undefined; const labelHighlights = wordFilter(searchValue, label); const aliasHighlights = alias ? wordFilter(searchValue, alias) : null; @@ -547,15 +547,15 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { let category, label = title; if (action.item.category) { category = typeof action.item.category === 'string' ? action.item.category : action.item.category.value; - label = nls.localize('cat.title', "{0}: {1}", category, title); + label = localize('cat.title', "{0}: {1}", category, title); } if (label) { const labelHighlights = wordFilter(searchValue, label); // Add an 'alias' in original language when running in different locale - const aliasTitle = (!Language.isDefaultVariant() && typeof action.item.title !== 'string') ? action.item.title.original : null; - const aliasCategory = (!Language.isDefaultVariant() && category && action.item.category && typeof action.item.category !== 'string') ? action.item.category.original : null; + const aliasTitle = (!Language.isDefaultVariant() && typeof action.item.title !== 'string') ? action.item.title.original : undefined; + const aliasCategory = (!Language.isDefaultVariant() && category && action.item.category && typeof action.item.category !== 'string') ? action.item.category.original : undefined; let alias; if (aliasTitle && category) { alias = aliasCategory ? `${aliasCategory}: ${aliasTitle}` : `${category}: ${aliasTitle}`; @@ -590,7 +590,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { } getEmptyLabel(searchString: string): string { - return nls.localize('noCommandsMatching', "No commands matching"); + return localize('noCommandsMatching', "No commands matching"); } onClose(canceled: boolean): void { diff --git a/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts index 60a0a3da383..d6f0c2560da 100644 --- a/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts @@ -195,7 +195,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup { return this.deprecated ? { extraClasses: ['deprecated'] } : undefined; } - getHighlights(): [IHighlight[], IHighlight[] | undefined, IHighlight[] | undefined] { + getHighlights(): [IHighlight[] | undefined, IHighlight[] | undefined, IHighlight[] | undefined] { return [ this.deprecated ? [] : filters.createMatches(this.score), undefined, diff --git a/src/vs/workbench/contrib/scm/browser/mainPanel.ts b/src/vs/workbench/contrib/scm/browser/mainPanel.ts index 2e0f160671a..217ab0acc4b 100644 --- a/src/vs/workbench/contrib/scm/browser/mainPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/mainPanel.ts @@ -10,7 +10,6 @@ import { basename } from 'vs/base/common/resources'; import { IDisposable, dispose, Disposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet'; import { append, $, toggleClass } from 'vs/base/browser/dom'; -import { List } from 'vs/base/browser/ui/list/listWidget'; import { IListVirtualDelegate, IListRenderer, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list'; import { ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; @@ -173,7 +172,7 @@ export class MainPanel extends ViewletPanel { static readonly ID = 'scm.mainPanel'; static readonly TITLE = localize('scm providers', "Source Control Providers"); - private list!: List; + private list!: WorkbenchList; constructor( protected viewModel: IViewModel, diff --git a/src/vs/workbench/contrib/search/browser/openSymbolHandler.ts b/src/vs/workbench/contrib/search/browser/openSymbolHandler.ts index c0bcedcb221..06bad345969 100644 --- a/src/vs/workbench/contrib/search/browser/openSymbolHandler.ts +++ b/src/vs/workbench/contrib/search/browser/openSymbolHandler.ts @@ -47,7 +47,7 @@ class SymbolEntry extends EditorQuickOpenEntry { this.score = score; } - getHighlights(): [IHighlight[] /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] { + getHighlights(): [IHighlight[] | undefined /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] { return [this.isDeprecated() ? [] : filters.createMatches(this.score), undefined, undefined]; } From c47430355669ead188ec397face22e89168a188c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 14:32:40 +0200 Subject: [PATCH 221/435] Remove .txt from save as simple file dialog Fixes https://github.com/microsoft/vscode/issues/73580 --- .../services/dialogs/browser/simpleFileDialog.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index f8f7325be35..bfcbf7000e0 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -255,16 +255,6 @@ export class SimpleFileDialog { homedir = resources.dirname(this.options.defaultUri); this.trailing = resources.basename(this.options.defaultUri); } - // append extension - if (isSave && !ext && this.options.filters) { - for (let i = 0; i < this.options.filters.length; i++) { - if (this.options.filters[i].extensions[0] !== '*') { - ext = '.' + this.options.filters[i].extensions[0]; - this.trailing = this.trailing ? this.trailing + ext : ext; - break; - } - } - } } return new Promise(async (resolve) => { From 5847d75aad757d1653ce8f188bb1743cccae9be7 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 14:35:05 +0200 Subject: [PATCH 222/435] fixes #81879 --- src/vs/workbench/contrib/debug/common/debugModel.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index ec8d05b8078..e93db64d746 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -617,8 +617,7 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint { } get column(): number | undefined { - // Only respect the column if the user explictly set the column to have an inline breakpoint - return this.verified && this.data && typeof this.data.column === 'number' && typeof this._column === 'number' ? this.data.column : this._column; + return this.verified && this.data && typeof this.data.column === 'number' ? this.data.column : this._column; } get message(): string | undefined { From a634057990a280bc3589b975b59776ccb8b7e6af Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 14:44:13 +0200 Subject: [PATCH 223/435] Uppercase drive letter on Windows simple file dialog Fixes #81949 --- src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index bfcbf7000e0..5e42ee3baf6 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -35,6 +35,7 @@ import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { toResource } from 'vs/workbench/common/editor'; +import { normalizeDriveLetter } from 'vs/base/common/labels'; export namespace OpenLocalFileCommand { export const ID = 'workbench.action.files.openLocalFile'; @@ -797,7 +798,7 @@ export class SimpleFileDialog { } private pathFromUri(uri: URI, endWithSeparator: boolean = false): string { - let result: string = uri.fsPath.replace(/\n/g, ''); + let result: string = normalizeDriveLetter(uri.fsPath).replace(/\n/g, ''); if (this.separator === '/') { result = result.replace(/\\/g, this.separator); } else { From bc8346120d4053b3379a9ccebcf4df1327b0529d Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 14:46:22 +0200 Subject: [PATCH 224/435] fixes #81662 --- .../contrib/files/browser/views/emptyView.ts | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index 60c0027a6df..f24f0128c6f 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -33,7 +33,6 @@ export class EmptyView extends ViewletPanel { private button!: Button; private messageElement!: HTMLElement; - private titleElement!: HTMLElement; constructor( options: IViewletViewOptions, @@ -52,19 +51,6 @@ export class EmptyView extends ViewletPanel { this._register(this.labelService.onDidChangeFormatters(() => this.setLabels())); } - renderHeader(container: HTMLElement): void { - const twisties = document.createElement('div'); - DOM.addClasses(twisties, 'twisties', 'codicon', 'codicon-chevron-right'); - container.appendChild(twisties); - - const titleContainer = document.createElement('div'); - DOM.addClass(titleContainer, 'title'); - container.appendChild(titleContainer); - - this.titleElement = document.createElement('span'); - titleContainer.appendChild(this.titleElement); - } - protected renderBody(container: HTMLElement): void { DOM.addClass(container, 'explorer-empty-view'); container.tabIndex = 0; @@ -129,7 +115,7 @@ export class EmptyView extends ViewletPanel { if (this.button) { this.button.label = nls.localize('addFolder', "Add Folder"); } - this.titleElement.textContent = EmptyView.NAME; + this.updateTitle(EmptyView.NAME); } else { if (this.environmentService.configuration.remoteAuthority && !isWeb) { const hostLabel = this.labelService.getHostLabel(Schemas.vscodeRemote, this.environmentService.configuration.remoteAuthority); @@ -140,7 +126,7 @@ export class EmptyView extends ViewletPanel { if (this.button) { this.button.label = nls.localize('openFolder', "Open Folder"); } - this.titleElement.textContent = this.title; + this.updateTitle(this.title); } } From 4fb9d0dbdc117186cffd3e132c555ba3e06f3f4f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 14:52:47 +0200 Subject: [PATCH 225/435] Don't show folders with trailing slash in simple file dialog pick Fixes #81911 --- .../services/dialogs/browser/simpleFileDialog.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 5e42ee3baf6..e83748f5e23 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -477,7 +477,7 @@ export class SimpleFileDialog { const newPath = this.pathFromUri(item.uri); if (startsWithIgnoreCase(newPath, this.filePickBox.value) && (equalsIgnoreCase(item.label, resources.basename(item.uri)))) { this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder).length, this.filePickBox.value.length]; - this.insertText(newPath, item.label); + this.insertText(newPath, this.basenameWithTrailingSlash(item.uri)); } else if ((item.label === '..') && startsWithIgnoreCase(this.filePickBox.value, newPath)) { this.filePickBox.valueSelection = [newPath.length, this.filePickBox.value.length]; this.insertText(newPath, ''); @@ -593,7 +593,7 @@ export class SimpleFileDialog { this.autoCompletePathSegment = ''; return false; } - const itemBasename = this.trimTrailingSlash(quickPickItem.label); + const itemBasename = quickPickItem.label; // Either force the autocomplete, or the old value should be one smaller than the new value and match the new value. if (itemBasename === '..') { // Don't match on the up directory item ever. @@ -612,7 +612,7 @@ export class SimpleFileDialog { this.autoCompletePathSegment = ''; this.filePickBox.activeItems = [quickPickItem]; return true; - } else if (force && (!equalsIgnoreCase(quickPickItem.label, (this.userEnteredPathSegment + this.autoCompletePathSegment)))) { + } else if (force && (!equalsIgnoreCase(this.basenameWithTrailingSlash(quickPickItem.uri), (this.userEnteredPathSegment + this.autoCompletePathSegment)))) { this.userEnteredPathSegment = ''; this.autoCompletePathSegment = this.trimTrailingSlash(itemBasename); this.activeItem = quickPickItem; @@ -904,7 +904,7 @@ export class SimpleFileDialog { try { const stat = await this.fileService.resolve(fullPath); if (stat.isDirectory) { - filename = this.basenameWithTrailingSlash(fullPath); + filename = resources.basename(fullPath); fullPath = resources.addTrailingPathSeparator(fullPath, this.separator); return { label: filename, uri: fullPath, isFolder: true, iconClasses: getIconClasses(this.modelService, this.modeService, fullPath || undefined, FileKind.FOLDER) }; } else if (!stat.isDirectory && this.allowFileSelection && this.filterFile(fullPath)) { From 443f36dd973e5e4b493110109ded6e32ced3a976 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 15:52:17 +0200 Subject: [PATCH 226/435] Fix broken matches in custom tree --- src/vs/workbench/browser/parts/views/customView.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 03c709a0e06..fac5a071a9c 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -753,6 +753,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer ({ start, end })) : undefined; const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark; const iconUrl = icon ? URI.revive(icon) : null; const title = node.tooltip ? node.tooltip : resource ? undefined : label; @@ -762,9 +763,9 @@ class TreeRenderer extends Disposable implements ITreeRenderer('explorer.decorations'); - templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: createMatches(element.filterData) }); + templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: matches ? matches : createMatches(element.filterData) }); } else { - templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: createMatches(element.filterData) }); + templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: matches ? matches : createMatches(element.filterData) }); } templateData.icon.style.backgroundImage = iconUrl ? DOM.asCSSUrl(iconUrl) : ''; From 491eb9bbaf4bfc65874142fb53eeb698d5566e1e Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 16:16:42 +0200 Subject: [PATCH 227/435] Add logic for negative custom tree view highlight numbers and handle flipped highlight start and end Fixes #62211 --- .../browser/parts/views/customView.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index fac5a071a9c..7872aae6f0c 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -753,7 +753,23 @@ class TreeRenderer extends Disposable implements ITreeRenderer ({ start, end })) : undefined; + const matches = (treeItemLabel && treeItemLabel.highlights && label) ? treeItemLabel.highlights.map(([start, end]) => { + if ((Math.abs(start) > label.length) || (Math.abs(end) >= label.length)) { + return ({ start: 0, end: 0 }); + } + if (start < 0) { + start = label.length + start; + } + if (end < 0) { + end = label.length + end; + } + if (start > end) { + const swap = start; + start = end; + end = swap; + } + return ({ start, end }); + }) : undefined; const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark; const iconUrl = icon ? URI.revive(icon) : null; const title = node.tooltip ? node.tooltip : resource ? undefined : label; From 0d895b5bb81d08f6f4a2cb9fc49540373c7aec3f Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 16:18:50 +0200 Subject: [PATCH 228/435] debug: more async await --- .../contrib/debug/browser/debugActions.ts | 4 +- .../contrib/debug/browser/debugService.ts | 348 +++++++++--------- .../contrib/debug/browser/debugSession.ts | 4 +- .../workbench/contrib/debug/browser/repl.ts | 4 +- .../workbench/contrib/debug/common/debug.ts | 2 +- 5 files changed, 183 insertions(+), 179 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 3a2c52b0193..1ecdb87c297 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -367,8 +367,8 @@ export class FocusSessionAction extends AbstractDebugAction { super(id, label, '', debugService, keybindingService); } - run(session: IDebugSession): Promise { - this.debugService.focusStackFrame(undefined, undefined, session, true); + async run(session: IDebugSession): Promise { + await this.debugService.focusStackFrame(undefined, undefined, session, true); const stackFrame = this.debugService.getViewModel().focusedStackFrame; if (stackFrame) { return stackFrame.openInEditor(this.editorService, true); diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index ccb8004fccc..67d9634723e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -24,7 +24,6 @@ import * as debugactions from 'vs/workbench/contrib/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager'; import Constants from 'vs/workbench/contrib/markers/browser/constants'; import { ITaskService, ITaskSummary } from 'vs/workbench/contrib/tasks/common/taskService'; -import { TaskError } from 'vs/workbench/contrib/tasks/common/taskSystem'; import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/contrib/files/common/files'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -144,13 +143,13 @@ export class DebugService implements IDebugService { session.configuration.request = 'attach'; session.configuration.port = event.port; session.setSubId(event.subId); - this.launchOrAttachToSession(session).then(undefined, errors.onUnexpectedError); + this.launchOrAttachToSession(session); } })); this.toDispose.push(this.extensionHostDebugService.onTerminateSession(event => { const session = this.model.getSession(event.sessionId); if (session && session.subId === event.subId) { - session.disconnect().then(undefined, errors.onUnexpectedError); + session.disconnect(); } })); this.toDispose.push(this.extensionHostDebugService.onLogToSession(event => { @@ -253,90 +252,93 @@ export class DebugService implements IDebugService { * main entry point * properly manages compounds, checks for errors and handles the initializing state. */ - startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise { + async startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise { this.startInitializingState(); - // make sure to save all files and that the configuration is up to date - return this.extensionService.activateByEvent('onDebug').then(() => { - return this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined).then(() => { - return this.extensionService.whenInstalledExtensionsRegistered().then(() => { + try { + // make sure to save all files and that the configuration is up to date + await this.extensionService.activateByEvent('onDebug'); + await this.textFileService.saveAll(); + await this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined); + await this.extensionService.whenInstalledExtensionsRegistered(); - let config: IConfig | undefined; - let compound: ICompound | undefined; - if (!configOrName) { - configOrName = this.configurationManager.selectedConfiguration.name; + let config: IConfig | undefined; + let compound: ICompound | undefined; + if (!configOrName) { + configOrName = this.configurationManager.selectedConfiguration.name; + } + if (typeof configOrName === 'string' && launch) { + config = launch.getConfiguration(configOrName); + compound = launch.getCompound(configOrName); + + const sessions = this.model.getSessions(); + const alreadyRunningMessage = nls.localize('configurationAlreadyRunning', "There is already a debug configuration \"{0}\" running.", configOrName); + if (sessions.some(s => s.configuration.name === configOrName && (!launch || !launch.workspace || !s.root || s.root.uri.toString() === launch.workspace.uri.toString()))) { + throw new Error(alreadyRunningMessage); + } + if (compound && compound.configurations && sessions.some(p => compound!.configurations.indexOf(p.configuration.name) !== -1)) { + throw new Error(alreadyRunningMessage); + } + } else if (typeof configOrName !== 'string') { + config = configOrName; + } + + if (compound) { + // we are starting a compound debug, first do some error checking and than start each configuration in the compound + if (!compound.configurations) { + throw new Error(nls.localize({ key: 'compoundMustHaveConfigurations', comment: ['compound indicates a "compounds" configuration item', '"configurations" is an attribute and should not be localized'] }, + "Compound must have \"configurations\" attribute set in order to start multiple configurations.")); + } + + const values = await Promise.all(compound.configurations.map(configData => { + const name = typeof configData === 'string' ? configData : configData.name; + if (name === compound!.name) { + return Promise.resolve(false); } - if (typeof configOrName === 'string' && launch) { - config = launch.getConfiguration(configOrName); - compound = launch.getCompound(configOrName); - const sessions = this.model.getSessions(); - const alreadyRunningMessage = nls.localize('configurationAlreadyRunning', "There is already a debug configuration \"{0}\" running.", configOrName); - if (sessions.some(s => s.configuration.name === configOrName && (!launch || !launch.workspace || !s.root || s.root.uri.toString() === launch.workspace.uri.toString()))) { - return Promise.reject(new Error(alreadyRunningMessage)); + let launchForName: ILaunch | undefined; + if (typeof configData === 'string') { + const launchesContainingName = this.configurationManager.getLaunches().filter(l => !!l.getConfiguration(name)); + if (launchesContainingName.length === 1) { + launchForName = launchesContainingName[0]; + } else if (launch && launchesContainingName.length > 1 && launchesContainingName.indexOf(launch) >= 0) { + // If there are multiple launches containing the configuration give priority to the configuration in the current launch + launchForName = launch; + } else { + throw new Error(launchesContainingName.length === 0 ? nls.localize('noConfigurationNameInWorkspace', "Could not find launch configuration '{0}' in the workspace.", name) + : nls.localize('multipleConfigurationNamesInWorkspace', "There are multiple launch configurations '{0}' in the workspace. Use folder name to qualify the configuration.", name)); } - if (compound && compound.configurations && sessions.some(p => compound!.configurations.indexOf(p.configuration.name) !== -1)) { - return Promise.reject(new Error(alreadyRunningMessage)); + } else if (configData.folder) { + const launchesMatchingConfigData = this.configurationManager.getLaunches().filter(l => l.workspace && l.workspace.name === configData.folder && !!l.getConfiguration(configData.name)); + if (launchesMatchingConfigData.length === 1) { + launchForName = launchesMatchingConfigData[0]; + } else { + throw new Error(nls.localize('noFolderWithName', "Can not find folder with name '{0}' for configuration '{1}' in compound '{2}'.", configData.folder, configData.name, compound!.name)); } - } else if (typeof configOrName !== 'string') { - config = configOrName; } - if (compound) { - // we are starting a compound debug, first do some error checking and than start each configuration in the compound - if (!compound.configurations) { - return Promise.reject(new Error(nls.localize({ key: 'compoundMustHaveConfigurations', comment: ['compound indicates a "compounds" configuration item', '"configurations" is an attribute and should not be localized'] }, - "Compound must have \"configurations\" attribute set in order to start multiple configurations."))); - } + return this.createSession(launchForName, launchForName!.getConfiguration(name), options); + })); - return Promise.all(compound.configurations.map(configData => { - const name = typeof configData === 'string' ? configData : configData.name; - if (name === compound!.name) { - return Promise.resolve(false); - } + const result = values.every(success => !!success); // Compound launch is a success only if each configuration launched successfully + this.endInitializingState(); + return result; + } - let launchForName: ILaunch | undefined; - if (typeof configData === 'string') { - const launchesContainingName = this.configurationManager.getLaunches().filter(l => !!l.getConfiguration(name)); - if (launchesContainingName.length === 1) { - launchForName = launchesContainingName[0]; - } else if (launch && launchesContainingName.length > 1 && launchesContainingName.indexOf(launch) >= 0) { - // If there are multiple launches containing the configuration give priority to the configuration in the current launch - launchForName = launch; - } else { - return Promise.reject(new Error(launchesContainingName.length === 0 ? nls.localize('noConfigurationNameInWorkspace', "Could not find launch configuration '{0}' in the workspace.", name) - : nls.localize('multipleConfigurationNamesInWorkspace', "There are multiple launch configurations '{0}' in the workspace. Use folder name to qualify the configuration.", name))); - } - } else if (configData.folder) { - const launchesMatchingConfigData = this.configurationManager.getLaunches().filter(l => l.workspace && l.workspace.name === configData.folder && !!l.getConfiguration(configData.name)); - if (launchesMatchingConfigData.length === 1) { - launchForName = launchesMatchingConfigData[0]; - } else { - return Promise.reject(new Error(nls.localize('noFolderWithName', "Can not find folder with name '{0}' for configuration '{1}' in compound '{2}'.", configData.folder, configData.name, compound!.name))); - } - } + if (configOrName && !config) { + const message = !!launch ? nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", typeof configOrName === 'string' ? configOrName : JSON.stringify(configOrName)) : + nls.localize('launchJsonDoesNotExist', "'launch.json' does not exist."); + throw new Error(message); + } - return this.createSession(launchForName, launchForName!.getConfiguration(name), options); - })).then(values => values.every(success => !!success)); // Compound launch is a success only if each configuration launched successfully - } - - if (configOrName && !config) { - const message = !!launch ? nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", typeof configOrName === 'string' ? configOrName : JSON.stringify(configOrName)) : - nls.localize('launchJsonDoesNotExist', "'launch.json' does not exist."); - return Promise.reject(new Error(message)); - } - - return this.createSession(launch, config, options); - }); - })); - }).then(success => { + const result = await this.createSession(launch, config, options); + this.endInitializingState(); + return result; + } catch (err) { // make sure to get out of initializing state, and propagate the result - this.endInitializingState(); - return success; - }, err => { this.endInitializingState(); return Promise.reject(err); - }); + } } /** @@ -476,18 +478,18 @@ export class DebugService implements IDebugService { }); } - private launchOrAttachToSession(session: IDebugSession, forceFocus = false): Promise { + private async launchOrAttachToSession(session: IDebugSession, forceFocus = false): Promise { const dbgr = this.configurationManager.getDebugger(session.configuration.type); - return session.initialize(dbgr!).then(() => { - return session.launchOrAttach(session.configuration).then(() => { - if (forceFocus || !this.viewModel.focusedSession) { - this.focusStackFrame(undefined, undefined, session); - } - }); - }).then(undefined, err => { + try { + await session.initialize(dbgr!); + await session.launchOrAttach(session.configuration); + if (forceFocus || !this.viewModel.focusedSession) { + await this.focusStackFrame(undefined, undefined, session); + } + } catch (err) { session.shutdown(); return Promise.reject(err); - }); + } } private registerSessionListeners(session: IDebugSession): void { @@ -506,7 +508,7 @@ export class DebugService implements IDebugService { } })); - this.toDispose.push(session.onDidEndAdapter(adapterExitEvent => { + this.toDispose.push(session.onDidEndAdapter(async adapterExitEvent => { if (adapterExitEvent.error) { this.notificationService.error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly ({0})", adapterExitEvent.error.message || adapterExitEvent.error.toString())); @@ -520,9 +522,11 @@ export class DebugService implements IDebugService { this.telemetryDebugSessionStop(session, adapterExitEvent); if (session.configuration.postDebugTask) { - this.runTask(session.root, session.configuration.postDebugTask).then(undefined, err => - this.notificationService.error(err) - ); + try { + await this.runTask(session.root, session.configuration.postDebugTask); + } catch (err) { + this.notificationService.error(err); + } } session.shutdown(); this.endInitializingState(); @@ -530,7 +534,7 @@ export class DebugService implements IDebugService { const focusedSession = this.viewModel.focusedSession; if (focusedSession && focusedSession.getId() === session.getId()) { - this.focusStackFrame(undefined); + await this.focusStackFrame(undefined); } if (this.model.getSessions().length === 0) { @@ -681,9 +685,9 @@ export class DebugService implements IDebugService { //---- task management - private runTaskAndCheckErrors(root: IWorkspaceFolder | undefined, taskId: string | TaskIdentifier | undefined): Promise { - - return this.runTask(root, taskId).then((taskSummary: ITaskSummary) => { + private async runTaskAndCheckErrors(root: IWorkspaceFolder | undefined, taskId: string | TaskIdentifier | undefined): Promise { + try { + const taskSummary = await this.runTask(root, taskId); const errorCount = taskId ? this.markerService.getStatistics().errors : 0; const successExitCode = taskSummary && taskSummary.exitCode === 0; @@ -702,34 +706,35 @@ export class DebugService implements IDebugService { ? nls.localize('preLaunchTaskErrors', "Errors exist after running preLaunchTask '{0}'.", taskLabel) : errorCount === 1 ? nls.localize('preLaunchTaskError', "Error exists after running preLaunchTask '{0}'.", taskLabel) - : nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", taskLabel, taskSummary.exitCode); + : nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", taskLabel, taskSummary ? taskSummary.exitCode : 0); - return this.dialogService.show(severity.Warning, message, [nls.localize('debugAnyway', "Debug Anyway"), nls.localize('showErrors', "Show Errors"), nls.localize('cancel', "Cancel")], { + const result = await this.dialogService.show(severity.Warning, message, [nls.localize('debugAnyway', "Debug Anyway"), nls.localize('showErrors', "Show Errors"), nls.localize('cancel', "Cancel")], { checkbox: { label: nls.localize('remember', "Remember my choice in user settings"), }, cancelId: 2 - }).then(result => { - if (result.choice === 2) { - return Promise.resolve(TaskRunResult.Failure); - } - const debugAnyway = result.choice === 0; - if (result.checkboxChecked) { - this.configurationService.updateValue('debug.onTaskErrors', debugAnyway ? 'debugAnyway' : 'showErrors'); - } - if (debugAnyway) { - return TaskRunResult.Success; - } - - this.panelService.openPanel(Constants.MARKERS_PANEL_ID); - return Promise.resolve(TaskRunResult.Failure); }); - }, (err: TaskError) => { - return this.showError(err.message, [this.taskService.configureAction()]); - }); + + if (result.choice === 2) { + return Promise.resolve(TaskRunResult.Failure); + } + const debugAnyway = result.choice === 0; + if (result.checkboxChecked) { + this.configurationService.updateValue('debug.onTaskErrors', debugAnyway ? 'debugAnyway' : 'showErrors'); + } + if (debugAnyway) { + return TaskRunResult.Success; + } + + this.panelService.openPanel(Constants.MARKERS_PANEL_ID); + return Promise.resolve(TaskRunResult.Failure); + } catch (err) { + await this.showError(err.message, [this.taskService.configureAction()]); + return TaskRunResult.Failure; + } } - private runTask(root: IWorkspaceFolder | undefined, taskId: string | TaskIdentifier | undefined): Promise { + private async runTask(root: IWorkspaceFolder | undefined, taskId: string | TaskIdentifier | undefined): Promise { if (!taskId) { return Promise.resolve(null); } @@ -737,58 +742,57 @@ export class DebugService implements IDebugService { return Promise.reject(new Error(nls.localize('invalidTaskReference', "Task '{0}' can not be referenced from a launch configuration that is in a different workspace folder.", typeof taskId === 'string' ? taskId : taskId.type))); } // run a task before starting a debug session - return this.taskService.getTask(root, taskId).then(task => { - if (!task) { - const errorMessage = typeof taskId === 'string' - ? nls.localize('DebugTaskNotFoundWithTaskId', "Could not find the task '{0}'.", taskId) - : nls.localize('DebugTaskNotFound', "Could not find the specified task."); - return Promise.reject(createErrorWithActions(errorMessage)); + const task = await this.taskService.getTask(root, taskId); + if (!task) { + const errorMessage = typeof taskId === 'string' + ? nls.localize('DebugTaskNotFoundWithTaskId', "Could not find the task '{0}'.", taskId) + : nls.localize('DebugTaskNotFound', "Could not find the specified task."); + return Promise.reject(createErrorWithActions(errorMessage)); + } + + // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 + let taskStarted = false; + const promise: Promise = this.taskService.getActiveTasks().then(tasks => { + if (tasks.filter(t => t._id === task._id).length) { + // task is already running - nothing to do. + return Promise.resolve(null); + } + once(e => ((e.kind === TaskEventKind.Active) || (e.kind === TaskEventKind.DependsOnStarted)) && e.taskId === task._id, this.taskService.onDidStateChange)(() => { + // Task is active, so everything seems to be fine, no need to prompt after 10 seconds + // Use case being a slow running task should not be prompted even though it takes more than 10 seconds + taskStarted = true; + }); + const taskPromise = this.taskService.run(task); + if (task.configurationProperties.isBackground) { + return new Promise((c, e) => once(e => e.kind === TaskEventKind.Inactive && e.taskId === task._id, this.taskService.onDidStateChange)(() => { + taskStarted = true; + c(null); + })); } - // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 - let taskStarted = false; - const promise: Promise = this.taskService.getActiveTasks().then(tasks => { - if (tasks.filter(t => t._id === task._id).length) { - // task is already running - nothing to do. - return Promise.resolve(null); + return taskPromise; + }); + + return new Promise((c, e) => { + promise.then(result => { + taskStarted = true; + c(result); + }, error => e(error)); + + setTimeout(() => { + if (!taskStarted) { + const errorMessage = typeof taskId === 'string' + ? nls.localize('taskNotTrackedWithTaskId', "The specified task cannot be tracked.") + : nls.localize('taskNotTracked', "The task '{0}' cannot be tracked.", JSON.stringify(taskId)); + e({ severity: severity.Error, message: errorMessage }); } - once(e => ((e.kind === TaskEventKind.Active) || (e.kind === TaskEventKind.DependsOnStarted)) && e.taskId === task._id, this.taskService.onDidStateChange)(() => { - // Task is active, so everything seems to be fine, no need to prompt after 10 seconds - // Use case being a slow running task should not be prompted even though it takes more than 10 seconds - taskStarted = true; - }); - const taskPromise = this.taskService.run(task); - if (task.configurationProperties.isBackground) { - return new Promise((c, e) => once(e => e.kind === TaskEventKind.Inactive && e.taskId === task._id, this.taskService.onDidStateChange)(() => { - taskStarted = true; - c(null); - })); - } - - return taskPromise; - }); - - return new Promise((c, e) => { - promise.then(result => { - taskStarted = true; - c(result); - }, error => e(error)); - - setTimeout(() => { - if (!taskStarted) { - const errorMessage = typeof taskId === 'string' - ? nls.localize('taskNotTrackedWithTaskId', "The specified task cannot be tracked.") - : nls.localize('taskNotTracked', "The task '{0}' cannot be tracked.", JSON.stringify(taskId)); - e({ severity: severity.Error, message: errorMessage }); - } - }, 10000); - }); + }, 10000); }); } //---- focus management - focusStackFrame(stackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): void { + async focusStackFrame(stackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): Promise { if (!session) { if (stackFrame || thread) { session = stackFrame ? stackFrame.thread.session : thread!.session; @@ -817,18 +821,17 @@ export class DebugService implements IDebugService { } if (stackFrame) { - stackFrame.openInEditor(this.editorService, true).then(editor => { - if (editor) { - const control = editor.getControl(); - if (stackFrame && isCodeEditor(control) && control.hasModel()) { - const model = control.getModel(); - if (stackFrame.range.startLineNumber <= model.getLineCount()) { - const lineContent = control.getModel().getLineContent(stackFrame.range.startLineNumber); - aria.alert(nls.localize('debuggingPaused', "Debugging paused {0}, {1} {2} {3}", thread && thread.stoppedDetails ? `, reason ${thread.stoppedDetails.reason}` : '', stackFrame.source ? stackFrame.source.name : '', stackFrame.range.startLineNumber, lineContent)); - } + const editor = await stackFrame.openInEditor(this.editorService, true); + if (editor) { + const control = editor.getControl(); + if (stackFrame && isCodeEditor(control) && control.hasModel()) { + const model = control.getModel(); + if (stackFrame.range.startLineNumber <= model.getLineCount()) { + const lineContent = control.getModel().getLineContent(stackFrame.range.startLineNumber); + aria.alert(nls.localize('debuggingPaused', "Debugging paused {0}, {1} {2} {3}", thread && thread.stoppedDetails ? `, reason ${thread.stoppedDetails.reason}` : '', stackFrame.source ? stackFrame.source.name : '', stackFrame.range.startLineNumber, lineContent)); } } - }); + } } if (session) { this.debugType.set(session.configuration.type); @@ -949,12 +952,12 @@ export class DebugService implements IDebugService { this.storeBreakpoints(); } - sendAllBreakpoints(session?: IDebugSession): Promise { - return Promise.all(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session))) - .then(() => this.sendFunctionBreakpoints(session)) - // send exception breakpoints at the end since some debug adapters rely on the order - .then(() => this.sendExceptionBreakpoints(session)) - .then(() => this.sendDataBreakpoints(session)); + async sendAllBreakpoints(session?: IDebugSession): Promise { + await Promise.all(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session))); + await this.sendFunctionBreakpoints(session); + await this.sendDataBreakpoints(session); + // send exception breakpoints at the end since some debug adapters rely on the order + await this.sendExceptionBreakpoints(session); } private sendBreakpoints(modelUri: uri, sourceModified = false, session?: IDebugSession): Promise { @@ -989,11 +992,12 @@ export class DebugService implements IDebugService { }); } - private sendToOneOrAllSessions(session: IDebugSession | undefined, send: (session: IDebugSession) => Promise): Promise { + private async sendToOneOrAllSessions(session: IDebugSession | undefined, send: (session: IDebugSession) => Promise): Promise { if (session) { - return send(session); + await send(session); + } else { + await Promise.all(this.model.getSessions().map(s => send(s))); } - return Promise.all(this.model.getSessions().map(s => send(s))).then(() => undefined); } private onFileChanges(fileChangesEvent: FileChangesEvent): void { diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index fcec6934cfb..bf8a93ef6de 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -727,9 +727,9 @@ export class DebugSession implements IDebugSession { // Call fetch call stack twice, the first only return the top stack frame. // Second retrieves the rest of the call stack. For performance reasons #25605 const promises = this.model.fetchCallStack(thread); - const focus = () => { + const focus = async () => { if (!event.body.preserveFocusHint && thread.getCallStack().length) { - this.debugService.focusStackFrame(undefined, thread); + await this.debugService.focusStackFrame(undefined, thread); if (thread.stoppedDetails) { if (this.configurationService.getValue('debug').openDebug === 'openOnDebugBreak') { this.viewletService.openViewlet(VIEWLET_ID); diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index ea0f700bb49..f15a1324cba 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -991,10 +991,10 @@ class SelectReplAction extends Action { super(id, label); } - run(session: IDebugSession): Promise { + async run(session: IDebugSession): Promise { // If session is already the focused session we need to manualy update the tree since view model will not send a focused change event if (session && session.state !== State.Inactive && session !== this.debugService.getViewModel().focusedSession) { - this.debugService.focusStackFrame(undefined, undefined, session, true); + await this.debugService.focusStackFrame(undefined, undefined, session, true); } else { this.replService.selectSession(session); } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index c68bc35d6ab..5438069c05a 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -732,7 +732,7 @@ export interface IDebugService { /** * Sets the focused stack frame and evaluates all expressions against the newly focused stack frame, */ - focusStackFrame(focusedStackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): void; + focusStackFrame(focusedStackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): Promise; /** * Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes. From f380a8b0479e156cdc64fdbfc1314a4d49a11aa4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 7 Oct 2019 07:34:55 -0700 Subject: [PATCH 229/435] Simplify fix for #12574 Related xtermjs/xterm.js#291 --- .../contrib/terminal/browser/terminalInstance.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index d8b97df7808..ef6bdddec6f 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -408,14 +408,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // The panel is minimized if (!this._isVisible) { return TerminalInstance._lastKnownCanvasDimensions; - } else { - // Trigger scroll event manually so that the viewport's scroll area is synced. This - // needs to happen otherwise its scrollTop value is invalid when the panel is toggled as - // it gets removed and then added back to the DOM (resetting scrollTop to 0). - // Upstream issue: https://github.com/sourcelair/xterm.js/issues/291 - if (this._xterm && this._xtermCore) { - this._xtermCore._onScroll.fire(this._xterm.buffer.viewportY); - } } if (!this._wrapperElement) { @@ -902,6 +894,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // necessary if the number of rows in the terminal has decreased while it was in the // background since scrollTop changes take no effect but the terminal's position does // change since the number of visible rows decreases. + // This can likely be removed after https://github.com/xtermjs/xterm.js/issues/291 is + // fixed upstream. this._xtermCore._onScroll.fire(this._xterm.buffer.viewportY); if (this._container && this._container.parentElement) { // Force a layout when the instance becomes invisible. This is particularly important From 2d713ac3a5385224a40ec6911195b14ac5a26139 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 16:39:18 +0200 Subject: [PATCH 230/435] debug: more async await --- .../contrib/debug/browser/debugService.ts | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 67d9634723e..32aada3b867 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -344,7 +344,7 @@ export class DebugService implements IDebugService { /** * gets the debugger for the type, resolves configurations by providers, substitutes variables and runs prelaunch tasks */ - private createSession(launch: ILaunch | undefined, config: IConfig | undefined, options?: IDebugSessionOptions): Promise { + private async createSession(launch: ILaunch | undefined, config: IConfig | undefined, options?: IDebugSessionOptions): Promise { // We keep the debug type in a separate variable 'type' so that a no-folder config has no attributes. // Storing the type in the config would break extensions that assume that the no-folder case is indicated by an empty config. let type: string | undefined; @@ -360,60 +360,65 @@ export class DebugService implements IDebugService { config!.noDebug = true; } - const debuggerThenable: Promise = type ? Promise.resolve() : this.configurationManager.guessDebugger().then(dbgr => { type = dbgr && dbgr.type; }); - return debuggerThenable.then(() => { - this.initCancellationToken = new CancellationTokenSource(); - return this.configurationManager.resolveConfigurationByProviders(launch && launch.workspace ? launch.workspace.uri : undefined, type, config!, this.initCancellationToken.token).then(config => { - // a falsy config indicates an aborted launch - if (config && config.type) { - return this.substituteVariables(launch, config).then(resolvedConfig => { + if (!type) { + const guess = await this.configurationManager.guessDebugger(); + if (guess) { + type = guess.type; + } + } - if (!resolvedConfig) { - // User canceled resolving of interactive variables, silently return - return false; - } + this.initCancellationToken = new CancellationTokenSource(); + const configByProviders = await this.configurationManager.resolveConfigurationByProviders(launch && launch.workspace ? launch.workspace.uri : undefined, type, config!, this.initCancellationToken.token); + // a falsy config indicates an aborted launch + if (configByProviders && configByProviders.type) { + try { + const resolvedConfig = await this.substituteVariables(launch, configByProviders); - if (!this.configurationManager.getDebugger(resolvedConfig.type) || (config.request !== 'attach' && config.request !== 'launch')) { - let message: string; - if (config.request !== 'attach' && config.request !== 'launch') { - message = config.request ? nls.localize('debugRequestNotSupported', "Attribute '{0}' has an unsupported value '{1}' in the chosen debug configuration.", 'request', config.request) - : nls.localize('debugRequesMissing', "Attribute '{0}' is missing from the chosen debug configuration.", 'request'); - - } else { - message = resolvedConfig.type ? nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", resolvedConfig.type) : - nls.localize('debugTypeMissing', "Missing property 'type' for the chosen launch configuration."); - } - - return this.showError(message).then(() => false); - } - - const workspace = launch ? launch.workspace : undefined; - return this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask).then(result => { - if (result === TaskRunResult.Success) { - return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, options); - } - return false; - }); - }, err => { - if (err && err.message) { - return this.showError(err.message).then(() => false); - } - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { - return this.showError(nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved and that you have a debug extension installed for that file type.")) - .then(() => false); - } - - return !!launch && launch.openConfigFile(false, true, undefined, this.initCancellationToken ? this.initCancellationToken.token : undefined).then(() => false); - }); + if (!resolvedConfig) { + // User canceled resolving of interactive variables, silently return + return false; } - if (launch && type && config === null) { // show launch.json only for "config" being "null". - return launch.openConfigFile(false, true, type, this.initCancellationToken ? this.initCancellationToken.token : undefined).then(() => false); + if (!this.configurationManager.getDebugger(resolvedConfig.type) || (configByProviders.request !== 'attach' && configByProviders.request !== 'launch')) { + let message: string; + if (configByProviders.request !== 'attach' && configByProviders.request !== 'launch') { + message = configByProviders.request ? nls.localize('debugRequestNotSupported', "Attribute '{0}' has an unsupported value '{1}' in the chosen debug configuration.", 'request', configByProviders.request) + : nls.localize('debugRequesMissing', "Attribute '{0}' is missing from the chosen debug configuration.", 'request'); + + } else { + message = resolvedConfig.type ? nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", resolvedConfig.type) : + nls.localize('debugTypeMissing', "Missing property 'type' for the chosen launch configuration."); + } + + await this.showError(message); + return false; + } + + const workspace = launch ? launch.workspace : undefined; + const taskResult = await this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask); + if (taskResult === TaskRunResult.Success) { + return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, options); + } + return false; + } catch (err) { + if (err && err.message) { + await this.showError(err.message); + } else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + await this.showError(nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved and that you have a debug extension installed for that file type.")); + } + if (launch) { + await launch.openConfigFile(false, true, undefined, this.initCancellationToken ? this.initCancellationToken.token : undefined); } return false; - }); - }); + } + } + + if (launch && type && configByProviders === null) { // show launch.json only for "config" being "null". + await launch.openConfigFile(false, true, type, this.initCancellationToken ? this.initCancellationToken.token : undefined); + } + + return false; } /** @@ -650,7 +655,7 @@ export class DebugService implements IDebugService { return Promise.all(sessions.map(s => s.terminate())); } - private substituteVariables(launch: ILaunch | undefined, config: IConfig): Promise { + private async substituteVariables(launch: ILaunch | undefined, config: IConfig): Promise { const dbg = this.configurationManager.getDebugger(config.type); if (dbg) { let folder: IWorkspaceFolder | undefined = undefined; @@ -662,12 +667,12 @@ export class DebugService implements IDebugService { folder = folders[0]; } } - return dbg.substituteVariables(folder, config).then(config => { - return config; - }, (err: Error) => { + try { + return await dbg.substituteVariables(folder, config); + } catch (err) { this.showError(err.message); return undefined; // bail out - }); + } } return Promise.resolve(config); } From e14c86a791b878dbc0b1ead42573a465d8b6a1c1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Oct 2019 16:56:09 +0200 Subject: [PATCH 231/435] Add a useful message for when background tasks don't have a watching problem matcher Fixes #81887 --- src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts | 4 ++++ src/vs/workbench/contrib/tasks/common/problemCollectors.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 1c45953acdf..0eefb3607a7 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -527,6 +527,10 @@ export class TerminalTaskSystem implements ITaskSystem { if (task.configurationProperties.isBackground) { const problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers); let watchingProblemMatcher = new WatchingProblemCollector(problemMatchers, this.markerService, this.modelService, this.fileService); + if (!watchingProblemMatcher.isWatching()) { + this.appendOutput(nls.localize('TerminalTaskSystem.nonWatchingMatcher', 'Task {0} is a background task but uses a problem matcher without a background pattern', task._label)); + this.showOutput(); + } const toDispose = new DisposableStore(); let eventCounter: number = 0; toDispose.add(watchingProblemMatcher.onDidStateChange((event) => { diff --git a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts index 30333ecdc3d..70e9d1b1fb5 100644 --- a/src/vs/workbench/contrib/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/contrib/tasks/common/problemCollectors.ts @@ -524,4 +524,8 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement }); super.done(); } + + public isWatching(): boolean { + return this.backgroundPatterns.length > 0; + } } From a51693925e032b65c8facd046ec58a2f5827bfe5 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 17:02:30 +0200 Subject: [PATCH 232/435] fix compile error --- src/vs/workbench/contrib/debug/test/common/mockDebug.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index 9ce2b7f792e..9178e857417 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -40,7 +40,8 @@ export class MockDebugService implements IDebugService { throw new Error('not implemented'); } - public focusStackFrame(focusedStackFrame: IStackFrame): void { + public focusStackFrame(focusedStackFrame: IStackFrame): Promise { + throw new Error('not implemented'); } sendAllBreakpoints(session?: IDebugSession): Promise { From 111b4dccff9392d868e638dd894210decaa918b4 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 7 Oct 2019 19:05:14 +0200 Subject: [PATCH 233/435] debug: more async / await --- .../contrib/debug/browser/debugService.ts | 179 ++++++++++-------- 1 file changed, 95 insertions(+), 84 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 32aada3b867..cdef1b6d531 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -424,7 +424,7 @@ export class DebugService implements IDebugService { /** * instantiates the new session, initializes the session, registers session listeners and reports telemetry */ - private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, options?: IDebugSessionOptions): Promise { + private async doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, options?: IDebugSessionOptions): Promise { const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, options); this.model.addSession(session); @@ -438,10 +438,11 @@ export class DebugService implements IDebugService { const openDebug = this.configurationService.getValue('debug').openDebug; // Open debug viewlet based on the visibility of the side bar and openDebug setting. Do not open for 'run without debug' if (!configuration.resolved.noDebug && (openDebug === 'openOnSessionStart' || (openDebug === 'openOnFirstSessionStart' && this.viewModel.firstSessionStart))) { - this.viewletService.openViewlet(VIEWLET_ID).then(undefined, errors.onUnexpectedError); + await this.viewletService.openViewlet(VIEWLET_ID); } - return this.launchOrAttachToSession(session).then(() => { + try { + await this.launchOrAttachToSession(session); const internalConsoleOptions = session.configuration.internalConsoleOptions || this.configurationService.getValue('debug').internalConsoleOptions; if (internalConsoleOptions === 'openOnSessionStart' || (this.viewModel.firstSessionStart && internalConsoleOptions === 'openOnFirstSessionStart')) { @@ -459,12 +460,14 @@ export class DebugService implements IDebugService { // since the initialized response has arrived announce the new Session (including extensions) this._onDidNewSession.fire(session); - return this.telemetryDebugSessionStart(root, session.configuration.type); - }).then(() => true, (error: Error | string) => { + await this.telemetryDebugSessionStart(root, session.configuration.type); + + return true; + } catch (error) { if (errors.isPromiseCanceledError(error)) { // don't show 'canceled' error messages to the user #7906 - return Promise.resolve(false); + return false; } // Show the repl if some error got logged there #5870 @@ -474,13 +477,15 @@ export class DebugService implements IDebugService { if (session.configuration && session.configuration.request === 'attach' && session.configuration.__autoAttach) { // ignore attach timeouts in auto attach mode - return Promise.resolve(false); + return false; } const errorMessage = error instanceof Error ? error.message : error; this.telemetryDebugMisconfiguration(session.configuration ? session.configuration.type : undefined, errorMessage); - return this.showError(errorMessage, isErrorWithActions(error) ? error.actions : []).then(() => false); - }); + + await this.showError(errorMessage, isErrorWithActions(error) ? error.actions : []); + return false; + } } private async launchOrAttachToSession(session: IDebugSession, forceFocus = false): Promise { @@ -557,87 +562,93 @@ export class DebugService implements IDebugService { })); } - restartSession(session: IDebugSession, restartData?: any): Promise { - return this.textFileService.saveAll().then(() => { - const isAutoRestart = !!restartData; - const runTasks: () => Promise = () => { - if (isAutoRestart) { - // Do not run preLaunch and postDebug tasks for automatic restarts - return Promise.resolve(TaskRunResult.Success); + async restartSession(session: IDebugSession, restartData?: any): Promise { + await this.textFileService.saveAll(); + const isAutoRestart = !!restartData; + + const runTasks: () => Promise = async () => { + if (isAutoRestart) { + // Do not run preLaunch and postDebug tasks for automatic restarts + return Promise.resolve(TaskRunResult.Success); + } + + await this.runTask(session.root, session.configuration.postDebugTask); + return this.runTaskAndCheckErrors(session.root, session.configuration.preLaunchTask); + }; + + if (session.capabilities.supportsRestartRequest) { + const taskResult = await runTasks(); + if (taskResult === TaskRunResult.Success) { + await session.restart(); + } + + return; + } + + if (isExtensionHostDebugging(session.configuration)) { + const taskResult = await runTasks(); + if (taskResult === TaskRunResult.Success) { + this.extensionHostDebugService.reload(session.getId()); + } + + return; + } + + const shouldFocus = !!this.viewModel.focusedSession && session.getId() === this.viewModel.focusedSession.getId(); + // If the restart is automatic -> disconnect, otherwise -> terminate #55064 + if (isAutoRestart) { + await session.disconnect(true); + } else { + await session.terminate(true); + } + + return new Promise((c, e) => { + setTimeout(async () => { + const taskResult = await runTasks(); + if (taskResult !== TaskRunResult.Success) { + return; } - return this.runTask(session.root, session.configuration.postDebugTask) - .then(() => this.runTaskAndCheckErrors(session.root, session.configuration.preLaunchTask)); - }; + // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration + let needsToSubstitute = false; + let unresolved: IConfig | undefined; + const launch = session.root ? this.configurationManager.getLaunch(session.root.uri) : undefined; + if (launch) { + unresolved = launch.getConfiguration(session.configuration.name); + if (unresolved && !equals(unresolved, session.unresolvedConfiguration)) { + // Take the type from the session since the debug extension might overwrite it #21316 + unresolved.type = session.configuration.type; + unresolved.noDebug = session.configuration.noDebug; + needsToSubstitute = true; + } + } - if (session.capabilities.supportsRestartRequest) { - return runTasks().then(taskResult => taskResult === TaskRunResult.Success ? session.restart() : undefined); - } + let resolved: IConfig | undefined | null = session.configuration; + if (launch && needsToSubstitute && unresolved) { + this.initCancellationToken = new CancellationTokenSource(); + const resolvedByProviders = await this.configurationManager.resolveConfigurationByProviders(launch.workspace ? launch.workspace.uri : undefined, unresolved.type, unresolved, this.initCancellationToken.token); + if (resolvedByProviders) { + resolved = await this.substituteVariables(launch, resolvedByProviders); + } else { + resolved = resolvedByProviders; + } + } - if (isExtensionHostDebugging(session.configuration)) { - return runTasks().then(taskResult => taskResult === TaskRunResult.Success ? this.extensionHostDebugService.reload(session.getId()) : undefined); - } + if (!resolved) { + return c(undefined); + } - const shouldFocus = !!this.viewModel.focusedSession && session.getId() === this.viewModel.focusedSession.getId(); - // If the restart is automatic -> disconnect, otherwise -> terminate #55064 - return (isAutoRestart ? session.disconnect(true) : session.terminate(true)).then(() => { + session.setConfiguration({ resolved, unresolved }); + session.configuration.__restart = restartData; - return new Promise((c, e) => { - setTimeout(() => { - runTasks().then(taskResult => { - if (taskResult !== TaskRunResult.Success) { - return; - } - - // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration - let needsToSubstitute = false; - let unresolved: IConfig | undefined; - const launch = session.root ? this.configurationManager.getLaunch(session.root.uri) : undefined; - if (launch) { - unresolved = launch.getConfiguration(session.configuration.name); - if (unresolved && !equals(unresolved, session.unresolvedConfiguration)) { - // Take the type from the session since the debug extension might overwrite it #21316 - unresolved.type = session.configuration.type; - unresolved.noDebug = session.configuration.noDebug; - needsToSubstitute = true; - } - } - - let substitutionThenable: Promise = Promise.resolve(session.configuration); - if (launch && needsToSubstitute && unresolved) { - this.initCancellationToken = new CancellationTokenSource(); - substitutionThenable = this.configurationManager.resolveConfigurationByProviders(launch.workspace ? launch.workspace.uri : undefined, unresolved.type, unresolved, this.initCancellationToken.token) - .then(resolved => { - if (resolved) { - // start debugging - return this.substituteVariables(launch, resolved); - } else if (resolved === null) { - // abort debugging silently and open launch.json - return Promise.resolve(null); - } else { - // abort debugging silently - return Promise.resolve(undefined); - } - }); - } - substitutionThenable.then(resolved => { - - if (!resolved) { - return c(undefined); - } - - session.setConfiguration({ resolved, unresolved }); - session.configuration.__restart = restartData; - - this.launchOrAttachToSession(session, shouldFocus).then(() => { - this._onDidNewSession.fire(session); - c(undefined); - }, err => e(err)); - }); - }); - }, 300); - }); - }); + try { + await this.launchOrAttachToSession(session, shouldFocus); + this._onDidNewSession.fire(session); + c(undefined); + } catch (error) { + e(error); + } + }, 300); }); } From 61cd8be9e38246b6814b7718af5f2eaabbad0773 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 7 Oct 2019 10:48:39 -0700 Subject: [PATCH 234/435] Call resolveCommonTelemetryProperties in browser version of telemetry service --- .../browser/workbenchCommonProperties.ts | 14 ++++- .../telemetry/node/commonProperties.ts | 8 +-- .../node/workbenchCommonProperties.ts | 5 +- .../test/browser/commonProperties.test.ts | 62 +++++++++++++++++++ .../electron-browser/commonProperties.test.ts | 48 -------------- .../telemetry/browser/telemetryService.ts | 2 +- .../electron-browser/telemetryService.ts | 2 +- 7 files changed, 80 insertions(+), 61 deletions(-) create mode 100644 src/vs/platform/telemetry/test/browser/commonProperties.test.ts diff --git a/src/vs/platform/telemetry/browser/workbenchCommonProperties.ts b/src/vs/platform/telemetry/browser/workbenchCommonProperties.ts index ac0da4361f7..d70af9beefb 100644 --- a/src/vs/platform/telemetry/browser/workbenchCommonProperties.ts +++ b/src/vs/platform/telemetry/browser/workbenchCommonProperties.ts @@ -13,8 +13,16 @@ export const lastSessionDateStorageKey = 'telemetry.lastSessionDate'; import * as Platform from 'vs/base/common/platform'; import * as uuid from 'vs/base/common/uuid'; import { cleanRemoteAuthority } from 'vs/platform/telemetry/common/telemetryUtils'; +import { mixin } from 'vs/base/common/objects'; -export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, remoteAuthority?: string): Promise<{ [name: string]: string | undefined }> { +export async function resolveWorkbenchCommonProperties( + storageService: IStorageService, + commit: string | undefined, + version: string | undefined, + machineId: string, + remoteAuthority?: string, + resolveAdditionalProperties?: () => { [key: string]: any } +): Promise<{ [name: string]: string | undefined }> { const result: { [name: string]: string | undefined; } = Object.create(null); const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!; const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!; @@ -68,6 +76,10 @@ export async function resolveWorkbenchCommonProperties(storageService: IStorageS } }); + if (resolveAdditionalProperties) { + mixin(result, resolveAdditionalProperties()); + } + return result; } diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index 4d5c2cfd1b7..c408e75c739 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -7,7 +7,6 @@ import * as Platform from 'vs/base/common/platform'; import * as os from 'os'; import * as uuid from 'vs/base/common/uuid'; import { readFile } from 'vs/base/node/pfs'; -import { mixin } from 'vs/base/common/objects'; export async function resolveCommonProperties( commit: string | undefined, @@ -15,8 +14,7 @@ export async function resolveCommonProperties( machineId: string | undefined, msftInternalDomains: string[] | undefined, installSourcePath: string, - product?: string, - resolveAdditionalProperties?: () => { [key: string]: any } + product?: string ): Promise<{ [name: string]: string | boolean | undefined; }> { const result: { [name: string]: string | boolean | undefined; } = Object.create(null); @@ -80,10 +78,6 @@ export async function resolveCommonProperties( // ignore error } - if (resolveAdditionalProperties) { - mixin(result, resolveAdditionalProperties()); - } - return result; } diff --git a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts index 637090a6896..41b8fffcfc4 100644 --- a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts +++ b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts @@ -15,10 +15,9 @@ export async function resolveWorkbenchCommonProperties( machineId: string, msftInternalDomains: string[] | undefined, installSourcePath: string, - remoteAuthority?: string, - resolveAdditionalProperties?: () => { [key: string]: any } + remoteAuthority?: string ): Promise<{ [name: string]: string | boolean | undefined }> { - const result = await resolveCommonProperties(commit, version, machineId, msftInternalDomains, installSourcePath, undefined, resolveAdditionalProperties); + const result = await resolveCommonProperties(commit, version, machineId, msftInternalDomains, installSourcePath, undefined); const instanceId = storageService.get(instanceStorageKey, StorageScope.GLOBAL)!; const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!; const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!; diff --git a/src/vs/platform/telemetry/test/browser/commonProperties.test.ts b/src/vs/platform/telemetry/test/browser/commonProperties.test.ts new file mode 100644 index 00000000000..6355efaaac4 --- /dev/null +++ b/src/vs/platform/telemetry/test/browser/commonProperties.test.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as assert from 'assert'; +import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/browser/workbenchCommonProperties'; +import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage'; + +suite('Browser Telemetry - common properties', function () { + + const commit: string = (undefined)!; + const version: string = (undefined)!; + let testStorageService: IStorageService; + + setup(() => { + testStorageService = new InMemoryStorageService(); + }); + + test('mixes in additional properties', async function () { + const resolveCommonTelemetryProperties = () => { + return { + 'userId': '1' + }; + }; + + const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, resolveCommonTelemetryProperties); + + assert.ok('commitHash' in props); + assert.ok('sessionID' in props); + assert.ok('timestamp' in props); + assert.ok('common.platform' in props); + assert.ok('common.timesincesessionstart' in props); + assert.ok('common.sequence' in props); + assert.ok('version' in props); + assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); + assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); + assert.ok('common.isNewSession' in props, 'isNewSession'); + assert.ok('common.machineId' in props, 'machineId'); + + assert.equal(props['userId'], '1'); + }); + + test('mixes in additional dyanmic properties', async function () { + let i = 1; + const resolveCommonTelemetryProperties = () => { + return Object.defineProperties({}, { + 'userId': { + get: () => { + return i++; + }, + enumerable: true + } + }); + }; + + const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, resolveCommonTelemetryProperties); + assert.equal(props['userId'], '1'); + + const props2 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, resolveCommonTelemetryProperties); + assert.equal(props2['userId'], '2'); + }); +}); diff --git a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts index 138cd35a1fa..ee49c04ba3f 100644 --- a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts @@ -81,52 +81,4 @@ suite('Telemetry - common properties', function () { value2 = props['common.timesincesessionstart']; assert.ok(value1 !== value2, 'timesincesessionstart'); }); - - test('mixes in additional properties', async function () { - const resolveCommonTelemetryProperties = () => { - return { - 'userId': '1' - }; - }; - - const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource, undefined, resolveCommonTelemetryProperties); - - assert.ok('commitHash' in props); - assert.ok('sessionID' in props); - assert.ok('timestamp' in props); - assert.ok('common.platform' in props); - assert.ok('common.nodePlatform' in props); - assert.ok('common.nodeArch' in props); - assert.ok('common.timesincesessionstart' in props); - assert.ok('common.sequence' in props); - assert.ok('common.platformVersion' in props, 'platformVersion'); - assert.ok('version' in props); - assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); - assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); - assert.ok('common.isNewSession' in props, 'isNewSession'); - assert.ok('common.instanceId' in props, 'instanceId'); - assert.ok('common.machineId' in props, 'machineId'); - - assert.equal(props['userId'], '1'); - }); - - test('mixes in additional dyanmic properties', async function () { - let i = 1; - const resolveCommonTelemetryProperties = () => { - return Object.defineProperties({}, { - 'userId': { - get: () => { - return i++; - }, - enumerable: true - } - }); - }; - - const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource, undefined, resolveCommonTelemetryProperties); - assert.equal(props['userId'], '1'); - - const props2 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource, undefined, resolveCommonTelemetryProperties); - assert.equal(props2['userId'], '2'); - }); }); diff --git a/src/vs/workbench/services/telemetry/browser/telemetryService.ts b/src/vs/workbench/services/telemetry/browser/telemetryService.ts index a33b25a0e3a..b06ed3920cb 100644 --- a/src/vs/workbench/services/telemetry/browser/telemetryService.ts +++ b/src/vs/workbench/services/telemetry/browser/telemetryService.ts @@ -83,7 +83,7 @@ export class TelemetryService extends Disposable implements ITelemetryService { if (!environmentService.isExtensionDevelopment && !environmentService.args['disable-telemetry'] && !!productService.enableTelemetry && !!aiKey) { const config: ITelemetryServiceConfig = { appender: combinedAppender(new WebTelemetryAppender(aiKey, logService), new LogAppender(logService)), - commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority), + commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), piiPaths: [environmentService.appRoot] }; diff --git a/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts b/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts index a3e41e7f41e..84fac20658e 100644 --- a/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts +++ b/src/vs/workbench/services/telemetry/electron-browser/telemetryService.ts @@ -38,7 +38,7 @@ export class TelemetryService extends Disposable implements ITelemetryService { const channel = sharedProcessService.getChannel('telemetryAppender'); const config: ITelemetryServiceConfig = { appender: combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(logService)), - commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, productService.msftInternalDomains, environmentService.installSourcePath, environmentService.configuration.remoteAuthority, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), + commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, productService.msftInternalDomains, environmentService.installSourcePath, environmentService.configuration.remoteAuthority), piiPaths: environmentService.extensionsPath ? [environmentService.appRoot, environmentService.extensionsPath] : [environmentService.appRoot] }; From e4ec1518816c38c933885032607162cb575e09a6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 5 Oct 2019 09:20:11 -0700 Subject: [PATCH 235/435] Fixes more issues related to strictFunctionTypes For #81574 --- src/vs/workbench/browser/parts/views/viewsViewlet.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 76d8302ca88..239514051a2 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -64,6 +64,9 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView super(id, { showHeaderInTitleWhenSingleView, dnd: new DefaultPanelDndController() }, configurationService, layoutService, contextMenuService, telemetryService, themeService, storageService); const container = Registry.as(ViewContainerExtensions.ViewContainersRegistry).get(id); + if (!container) { + throw new Error('Could not find container'); + } this.viewsModel = this._register(this.instantiationService.createInstance(PersistentContributableViewsModel, container, viewletStateStorageId)); this.viewletState = this.getMemento(StorageScope.WORKSPACE); From 1f7e44562515e51b05e61271b72c7afc417d5c74 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 5 Oct 2019 09:27:16 -0700 Subject: [PATCH 236/435] Fixing more issues related to TS 3.7 dom typings changes Fixes cases where styles value can no longer be null --- .../base/browser/ui/countBadge/countBadge.ts | 10 +++++----- src/vs/base/browser/ui/dialog/dialog.ts | 8 ++++---- src/vs/base/browser/ui/inputbox/inputBox.ts | 16 +++++++-------- src/vs/base/browser/ui/menu/menu.ts | 20 +++++++++---------- .../browser/ui/selectBox/selectBoxCustom.ts | 10 +++++----- .../browser/ui/selectBox/selectBoxNative.ts | 6 +++--- .../parts/activitybar/activitybarPart.ts | 20 +++++++++---------- .../browser/parts/editor/editorGroupView.ts | 8 ++++---- 8 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/vs/base/browser/ui/countBadge/countBadge.ts b/src/vs/base/browser/ui/countBadge/countBadge.ts index e4b1f68568f..cb04c5099f3 100644 --- a/src/vs/base/browser/ui/countBadge/countBadge.ts +++ b/src/vs/base/browser/ui/countBadge/countBadge.ts @@ -85,15 +85,15 @@ export class CountBadge { private applyStyles(): void { if (this.element) { - const background = this.badgeBackground ? this.badgeBackground.toString() : null; - const foreground = this.badgeForeground ? this.badgeForeground.toString() : null; - const border = this.badgeBorder ? this.badgeBorder.toString() : null; + const background = this.badgeBackground ? this.badgeBackground.toString() : ''; + const foreground = this.badgeForeground ? this.badgeForeground.toString() : ''; + const border = this.badgeBorder ? this.badgeBorder.toString() : ''; this.element.style.backgroundColor = background; this.element.style.color = foreground; - this.element.style.borderWidth = border ? '1px' : null; - this.element.style.borderStyle = border ? 'solid' : null; + this.element.style.borderWidth = border ? '1px' : ''; + this.element.style.borderStyle = border ? 'solid' : ''; this.element.style.borderColor = border; } } diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index 9be85097748..723bf64b975 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -241,10 +241,10 @@ export class Dialog extends Disposable { if (this.styles) { const style = this.styles; - const fgColor = style.dialogForeground ? `${style.dialogForeground}` : null; - const bgColor = style.dialogBackground ? `${style.dialogBackground}` : null; - const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : null; - const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : null; + const fgColor = style.dialogForeground ? `${style.dialogForeground}` : ''; + const bgColor = style.dialogBackground ? `${style.dialogBackground}` : ''; + const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : ''; + const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : ''; if (this.element) { this.element.style.color = fgColor; diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index d743e3bf9f2..a3cf52ca023 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -373,7 +373,7 @@ export class InputBox extends Widget { dom.addClass(this.element, this.classForType(message.type)); const styles = this.stylesForType(this.message.type); - this.element.style.border = styles.border ? `1px solid ${styles.border}` : null; + this.element.style.border = styles.border ? `1px solid ${styles.border}` : ''; // ARIA Support let alertText: string; @@ -473,9 +473,9 @@ export class InputBox extends Widget { dom.addClass(spanElement, this.classForType(this.message.type)); const styles = this.stylesForType(this.message.type); - spanElement.style.backgroundColor = styles.background ? styles.background.toString() : null; + spanElement.style.backgroundColor = styles.background ? styles.background.toString() : ''; spanElement.style.color = styles.foreground ? styles.foreground.toString() : null; - spanElement.style.border = styles.border ? `1px solid ${styles.border}` : null; + spanElement.style.border = styles.border ? `1px solid ${styles.border}` : ''; dom.append(div, spanElement); @@ -552,17 +552,17 @@ export class InputBox extends Widget { } protected applyStyles(): void { - const background = this.inputBackground ? this.inputBackground.toString() : null; - const foreground = this.inputForeground ? this.inputForeground.toString() : null; - const border = this.inputBorder ? this.inputBorder.toString() : null; + const background = this.inputBackground ? this.inputBackground.toString() : ''; + const foreground = this.inputForeground ? this.inputForeground.toString() : ''; + const border = this.inputBorder ? this.inputBorder.toString() : ''; this.element.style.backgroundColor = background; this.element.style.color = foreground; this.input.style.backgroundColor = background; this.input.style.color = foreground; - this.element.style.borderWidth = border ? '1px' : null; - this.element.style.borderStyle = border ? 'solid' : null; + this.element.style.borderWidth = border ? '1px' : ''; + this.element.style.borderStyle = border ? 'solid' : ''; this.element.style.borderColor = border; } diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index b81aee160eb..4e94f810672 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -204,7 +204,7 @@ export class Menu extends ActionBar { })); const scrollElement = this.scrollableElement.getDomNode(); - scrollElement.style.position = null; + scrollElement.style.position = ''; menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 30)}px`; @@ -231,10 +231,10 @@ export class Menu extends ActionBar { style(style: IMenuStyles): void { const container = this.getContainer(); - const fgColor = style.foregroundColor ? `${style.foregroundColor}` : null; - const bgColor = style.backgroundColor ? `${style.backgroundColor}` : null; - const border = style.borderColor ? `2px solid ${style.borderColor}` : null; - const shadow = style.shadowColor ? `0 2px 4px ${style.shadowColor}` : null; + const fgColor = style.foregroundColor ? `${style.foregroundColor}` : ''; + const bgColor = style.backgroundColor ? `${style.backgroundColor}` : ''; + const border = style.borderColor ? `2px solid ${style.borderColor}` : ''; + const shadow = style.shadowColor ? `0 2px 4px ${style.shadowColor}` : ''; container.style.border = border; this.domNode.style.color = fgColor; @@ -575,11 +575,11 @@ class BaseMenuActionViewItem extends BaseActionViewItem { const isSelected = this.element && hasClass(this.element, 'focused'); const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor; const bgColor = isSelected && this.menuStyle.selectionBackgroundColor ? this.menuStyle.selectionBackgroundColor : this.menuStyle.backgroundColor; - const border = isSelected && this.menuStyle.selectionBorderColor ? `thin solid ${this.menuStyle.selectionBorderColor}` : null; + const border = isSelected && this.menuStyle.selectionBorderColor ? `thin solid ${this.menuStyle.selectionBorderColor}` : ''; this.item.style.color = fgColor ? `${fgColor}` : null; - this.check.style.backgroundColor = fgColor ? `${fgColor}` : null; - this.item.style.backgroundColor = bgColor ? `${bgColor}` : null; + this.check.style.backgroundColor = fgColor ? `${fgColor}` : ''; + this.item.style.backgroundColor = bgColor ? `${bgColor}` : ''; this.container.style.border = border; } @@ -793,7 +793,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem { const isSelected = this.element && hasClass(this.element, 'focused'); const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor; - this.submenuIndicator.style.backgroundColor = fgColor ? `${fgColor}` : null; + this.submenuIndicator.style.backgroundColor = fgColor ? `${fgColor}` : ''; if (this.parentData.submenu) { this.parentData.submenu.style(this.menuStyle); @@ -819,7 +819,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem { class MenuSeparatorActionViewItem extends ActionViewItem { style(style: IMenuStyles): void { if (this.label) { - this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : null; + this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : ''; } } } diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index b5f2fe57c72..7e6ee0f7f6a 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -374,9 +374,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi // Style parent select if (this.selectElement) { - const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : null; - const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : null; - const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : null; + const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : ''; + const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : ''; + const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : ''; this.selectElement.style.backgroundColor = background; this.selectElement.style.color = foreground; @@ -392,10 +392,10 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi private styleList() { if (this.selectList) { - let background = this.styles.selectBackground ? this.styles.selectBackground.toString() : null; + const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : ''; this.selectList.style({}); - let listBackground = this.styles.selectListBackground ? this.styles.selectListBackground.toString() : background; + const listBackground = this.styles.selectListBackground ? this.styles.selectListBackground.toString() : background; this.selectDropDownListContainer.style.backgroundColor = listBackground; this.selectionDetailsPane.style.backgroundColor = listBackground; const optionsBorder = this.styles.focusBorder ? this.styles.focusBorder.toString() : ''; diff --git a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts index afaed056d4c..8c50b057fb5 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts @@ -147,9 +147,9 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate { // Style native select if (this.selectElement) { - const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : null; - const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : null; - const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : null; + const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : ''; + const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : ''; + const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : ''; this.selectElement.style.backgroundColor = background; this.selectElement.style.color = foreground; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 416d5f00da5..fc2f2bf42b8 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -247,7 +247,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.createGlobalActivityActionBar(globalActivities); - this.element.style.display = this.layoutService.isVisible(Parts.ACTIVITYBAR_PART) ? null : 'none'; + this.element.style.display = this.layoutService.isVisible(Parts.ACTIVITYBAR_PART) ? '' : 'none'; return this.content; } @@ -257,18 +257,18 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Part container const container = assertIsDefined(this.getContainer()); - const background = this.getColor(ACTIVITY_BAR_BACKGROUND); + const background = this.getColor(ACTIVITY_BAR_BACKGROUND) || ''; container.style.backgroundColor = background; - const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder); + const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || ''; const isPositionLeft = this.layoutService.getSideBarPosition() === SideBarPosition.LEFT; container.style.boxSizing = borderColor && isPositionLeft ? 'border-box' : ''; - container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : null; - container.style.borderRightStyle = borderColor && isPositionLeft ? 'solid' : null; - container.style.borderRightColor = isPositionLeft ? borderColor : null; - container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : null; - container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : null; - container.style.borderLeftColor = !isPositionLeft ? borderColor : null; + container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : ''; + container.style.borderRightStyle = borderColor && isPositionLeft ? 'solid' : ''; + container.style.borderRightColor = isPositionLeft ? borderColor : ''; + container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : ''; + container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : ''; + container.style.borderLeftColor = !isPositionLeft ? borderColor : ''; } private getActivitybarItemColors(theme: ITheme): ICompositeBarColors { @@ -421,7 +421,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { setVisible(visible: boolean): void { if (this.element) { - this.element.style.display = visible ? null : 'none'; + this.element.style.display = visible ? '' : 'none'; } } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 8f4e19ed022..9b1c072ff2e 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -1442,9 +1442,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Container if (isEmpty) { - this.element.style.backgroundColor = this.getColor(EDITOR_GROUP_EMPTY_BACKGROUND); + this.element.style.backgroundColor = this.getColor(EDITOR_GROUP_EMPTY_BACKGROUND) || ''; } else { - this.element.style.backgroundColor = null; + this.element.style.backgroundColor = ''; } // Title control @@ -1459,10 +1459,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this.titleContainer.style.removeProperty('--title-border-bottom-color'); } - this.titleContainer.style.backgroundColor = this.getColor(showTabs ? EDITOR_GROUP_HEADER_TABS_BACKGROUND : EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND); + this.titleContainer.style.backgroundColor = this.getColor(showTabs ? EDITOR_GROUP_HEADER_TABS_BACKGROUND : EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND) || ''; // Editor container - this.editorContainer.style.backgroundColor = this.getColor(editorBackground); + this.editorContainer.style.backgroundColor = this.getColor(editorBackground) || ''; } //#endregion From 9f90a1d69c288280c81b958493cac82c4a9eb23d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 5 Oct 2019 14:36:33 -0700 Subject: [PATCH 237/435] Fix more TS 3.7 dom typings errors Use an empty string instead of null for reseting styles --- src/vs/base/browser/ui/splitview/panelview.ts | 6 +++--- .../parts/quickopen/browser/quickOpenWidget.ts | 12 ++++++------ .../parts/notifications/notificationsCenter.ts | 6 +++--- .../parts/notifications/notificationsList.ts | 2 +- src/vs/workbench/browser/parts/panel/panelPart.ts | 12 ++++++------ .../browser/parts/quickinput/quickInputList.ts | 2 +- .../workbench/browser/parts/sidebar/sidebarPart.ts | 14 +++++++------- .../browser/parts/statusbar/statusbarPart.ts | 4 ++-- .../browser/parts/titlebar/titlebarPart.ts | 8 ++++---- .../contrib/debug/browser/debugActionViewItems.ts | 4 ++-- .../workbench/contrib/debug/browser/debugHover.ts | 4 ++-- .../contrib/debug/browser/debugToolBar.ts | 4 ++-- .../workbench/contrib/feedback/browser/feedback.ts | 10 +++++----- .../contrib/markers/browser/markersPanelActions.ts | 10 +++++----- 14 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 875537e8817..f7c63a466c6 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -229,8 +229,8 @@ export abstract class Panel extends Disposable implements IView { this.header.setAttribute('aria-expanded', String(expanded)); this.header.style.color = this.styles.headerForeground ? this.styles.headerForeground.toString() : null; - this.header.style.backgroundColor = this.styles.headerBackground ? this.styles.headerBackground.toString() : null; - this.header.style.borderTop = this.styles.headerBorder ? `1px solid ${this.styles.headerBorder}` : null; + this.header.style.backgroundColor = this.styles.headerBackground ? this.styles.headerBackground.toString() : ''; + this.header.style.borderTop = this.styles.headerBorder ? `1px solid ${this.styles.headerBorder}` : ''; this._dropBackground = this.styles.dropBackground; } @@ -340,7 +340,7 @@ class PanelDraggable extends Disposable { backgroundColor = (this.panel.dropBackground || PanelDraggable.DefaultDragOverBackgroundColor).toString(); } - this.panel.dropTargetElement.style.backgroundColor = backgroundColor; + this.panel.dropTargetElement.style.backgroundColor = backgroundColor || ''; } } diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index f5276b7baa3..7a3a473d970 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -396,16 +396,16 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { protected applyStyles(): void { if (this.element) { const foreground = this.styles.foreground ? this.styles.foreground.toString() : null; - const background = this.styles.background ? this.styles.background.toString() : null; - const borderColor = this.styles.borderColor ? this.styles.borderColor.toString() : null; - const widgetShadow = this.styles.widgetShadow ? this.styles.widgetShadow.toString() : null; + const background = this.styles.background ? this.styles.background.toString() : ''; + const borderColor = this.styles.borderColor ? this.styles.borderColor.toString() : ''; + const widgetShadow = this.styles.widgetShadow ? this.styles.widgetShadow.toString() : ''; this.element.style.color = foreground; this.element.style.backgroundColor = background; this.element.style.borderColor = borderColor; - this.element.style.borderWidth = borderColor ? '1px' : null; - this.element.style.borderStyle = borderColor ? 'solid' : null; - this.element.style.boxShadow = widgetShadow ? `0 5px 8px ${widgetShadow}` : null; + this.element.style.borderWidth = borderColor ? '1px' : ''; + this.element.style.borderStyle = borderColor ? 'solid' : ''; + this.element.style.boxShadow = widgetShadow ? `0 5px 8px ${widgetShadow}` : ''; } if (this.progressBar) { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index 77a4a66b55c..a05135564ea 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -227,16 +227,16 @@ export class NotificationsCenter extends Themable { protected updateStyles(): void { if (this.notificationsCenterContainer && this.notificationsCenterHeader) { const widgetShadowColor = this.getColor(widgetShadow); - this.notificationsCenterContainer.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : null; + this.notificationsCenterContainer.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : ''; const borderColor = this.getColor(NOTIFICATIONS_CENTER_BORDER); - this.notificationsCenterContainer.style.border = borderColor ? `1px solid ${borderColor}` : null; + this.notificationsCenterContainer.style.border = borderColor ? `1px solid ${borderColor}` : ''; const headerForeground = this.getColor(NOTIFICATIONS_CENTER_HEADER_FOREGROUND); this.notificationsCenterHeader.style.color = headerForeground ? headerForeground.toString() : null; const headerBackground = this.getColor(NOTIFICATIONS_CENTER_HEADER_BACKGROUND); - this.notificationsCenterHeader.style.background = headerBackground ? headerBackground.toString() : null; + this.notificationsCenterHeader.style.background = headerBackground ? headerBackground.toString() : ''; } } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index b2993d52599..7a83faeacfb 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -221,7 +221,7 @@ export class NotificationsList extends Themable { this.listContainer.style.color = foreground ? foreground.toString() : null; const background = this.getColor(NOTIFICATIONS_BACKGROUND); - this.listContainer.style.background = background ? background.toString() : null; + this.listContainer.style.background = background ? background.toString() : ''; const outlineColor = this.getColor(contrastBorder); this.listContainer.style.outlineColor = outlineColor ? outlineColor.toString() : ''; diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index c134e3b8d3a..4015b6dffc7 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -71,7 +71,7 @@ export class PanelPart extends CompositePart implements IPanelService { //#endregion - get onDidPanelOpen(): Event<{ panel: IPanel, focus: boolean }> { return Event.map(this.onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus })); } + get onDidPanelOpen(): Event<{ panel: IPanel, focus: boolean; }> { return Event.map(this.onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus })); } readonly onDidPanelClose: Event = this.onDidCompositeClose.event; private _onDidVisibilityChange = this._register(new Emitter()); @@ -81,7 +81,7 @@ export class PanelPart extends CompositePart implements IPanelService { private panelFocusContextKey: IContextKey; private compositeBar: CompositeBar; - private compositeActions: Map = new Map(); + private compositeActions: Map = new Map(); private blockOpeningPanel = false; private _contentDimension: Dimension | undefined; @@ -209,12 +209,12 @@ export class PanelPart extends CompositePart implements IPanelService { super.updateStyles(); const container = assertIsDefined(this.getContainer()); - container.style.backgroundColor = this.getColor(PANEL_BACKGROUND); - container.style.borderLeftColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder); + container.style.backgroundColor = this.getColor(PANEL_BACKGROUND) || ''; + container.style.borderLeftColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || ''; const title = this.getTitleArea(); if (title) { - title.style.borderTopColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder); + title.style.borderTopColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || ''; } } @@ -326,7 +326,7 @@ export class PanelPart extends CompositePart implements IPanelService { } } - private getCompositeActions(compositeId: string): { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction } { + private getCompositeActions(compositeId: string): { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction; } { let compositeActions = this.compositeActions.get(compositeId); if (!compositeActions) { compositeActions = { diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputList.ts b/src/vs/workbench/browser/parts/quickinput/quickInputList.ts index 4c992ffd94f..e94290fee50 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInputList.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInputList.ts @@ -159,7 +159,7 @@ class ListElementRenderer implements IListRenderer implements IViewletServi // Part container const container = assertIsDefined(this.getContainer()); - container.style.backgroundColor = this.getColor(SIDE_BAR_BACKGROUND); + container.style.backgroundColor = this.getColor(SIDE_BAR_BACKGROUND) || ''; container.style.color = this.getColor(SIDE_BAR_FOREGROUND); const borderColor = this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder); const isPositionLeft = this.layoutService.getSideBarPosition() === SideBarPosition.LEFT; - container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : null; - container.style.borderRightStyle = borderColor && isPositionLeft ? 'solid' : null; - container.style.borderRightColor = isPositionLeft ? borderColor : null; - container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : null; - container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : null; - container.style.borderLeftColor = !isPositionLeft ? borderColor : null; + container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : ''; + container.style.borderRightStyle = borderColor && isPositionLeft ? 'solid' : ''; + container.style.borderRightColor = isPositionLeft ? borderColor || '' : ''; + container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : ''; + container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : ''; + container.style.borderLeftColor = !isPositionLeft ? borderColor || '' : ''; } layout(width: number, height: number): void { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 11ec913abd8..5d73c777540 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -578,7 +578,7 @@ export class StatusbarPart extends Part implements IStatusbarService { const container = assertIsDefined(this.getContainer()); // Background colors - const backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND); + const backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND) || ''; container.style.backgroundColor = backgroundColor; container.style.color = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND); @@ -784,7 +784,7 @@ class StatusbarEntryItem extends Disposable { } if (isBackground) { - container.style.backgroundColor = colorResult; + container.style.backgroundColor = colorResult || ''; } else { container.style.color = colorResult; } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 1fc235927cb..bfc77a7aa5c 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -507,7 +507,7 @@ export class TitlebarPart extends Part implements ITitleService { removeClass(this.element, 'inactive'); } - const titleBackground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND); + const titleBackground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND) || ''; this.element.style.backgroundColor = titleBackground; if (titleBackground && Color.fromHex(titleBackground).isLighter()) { addClass(this.element, 'light'); @@ -519,7 +519,7 @@ export class TitlebarPart extends Part implements ITitleService { this.element.style.color = titleForeground; const titleBorder = this.getColor(TITLE_BAR_BORDER); - this.element.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : null; + this.element.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : ''; } } @@ -559,8 +559,8 @@ export class TitlebarPart extends Part implements ITitleService { // Center between menu and window controls if (leftMarker > (this.element.clientWidth - this.title.clientWidth) / 2 || rightMarker < (this.element.clientWidth + this.title.clientWidth) / 2) { - this.title.style.position = null; - this.title.style.left = null; + this.title.style.position = ''; + this.title.style.left = ''; this.title.style.transform = ''; return; } diff --git a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts index 7653bcd4d64..381e6df69cc 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts @@ -122,8 +122,8 @@ export class StartDebugActionViewItem implements IActionViewItem { } })); this.toDispose.push(attachStylerCallback(this.themeService, { selectBorder }, colors => { - this.container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : null; - selectBoxContainer.style.borderLeft = colors.selectBorder ? `1px solid ${colors.selectBorder}` : null; + this.container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : ''; + selectBoxContainer.style.borderLeft = colors.selectBorder ? `1px solid ${colors.selectBorder}` : ''; })); this.updateOptions(); diff --git a/src/vs/workbench/contrib/debug/browser/debugHover.ts b/src/vs/workbench/contrib/debug/browser/debugHover.ts index 506aafc1781..812f5961f1b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugHover.ts +++ b/src/vs/workbench/contrib/debug/browser/debugHover.ts @@ -94,12 +94,12 @@ export class DebugHoverWidget implements IContentWidget { if (colors.editorHoverBackground) { this.domNode.style.backgroundColor = colors.editorHoverBackground.toString(); } else { - this.domNode.style.backgroundColor = null; + this.domNode.style.backgroundColor = ''; } if (colors.editorHoverBorder) { this.domNode.style.border = `1px solid ${colors.editorHoverBorder}`; } else { - this.domNode.style.border = null; + this.domNode.style.border = ''; } })); this.toDispose.push(this.tree.onDidChangeContentHeight(() => this.layoutTreeAndContainer())); diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index ba384a37df3..f20ab5d427a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -192,10 +192,10 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { super.updateStyles(); if (this.$el) { - this.$el.style.backgroundColor = this.getColor(debugToolBarBackground); + this.$el.style.backgroundColor = this.getColor(debugToolBarBackground) || ''; const widgetShadowColor = this.getColor(widgetShadow); - this.$el.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null; + this.$el.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : ''; const contrastBorderColor = this.getColor(contrastBorder); const borderColor = this.getColor(debugToolBarBorder); diff --git a/src/vs/workbench/contrib/feedback/browser/feedback.ts b/src/vs/workbench/contrib/feedback/browser/feedback.ts index 2721433b39f..ae6f9bcbbd7 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedback.ts @@ -142,7 +142,7 @@ export class FeedbackDropdown extends Dropdown { })); disposables.add(dom.addDisposableListener(closeBtn, dom.EventType.MOUSE_OUT, () => { - closeBtn.style.backgroundColor = null; + closeBtn.style.backgroundColor = ''; })); this.invoke(closeBtn, disposables, () => this.hide()); @@ -276,17 +276,17 @@ export class FeedbackDropdown extends Dropdown { disposables.add(attachStylerCallback(this.themeService, { widgetShadow, editorWidgetBackground, editorWidgetForeground, inputBackground, inputForeground, inputBorder, editorBackground, contrastBorder }, colors => { if (this.feedbackForm) { - this.feedbackForm.style.backgroundColor = colors.editorWidgetBackground ? colors.editorWidgetBackground.toString() : null; + this.feedbackForm.style.backgroundColor = colors.editorWidgetBackground ? colors.editorWidgetBackground.toString() : ''; this.feedbackForm.style.color = colors.editorWidgetForeground ? colors.editorWidgetForeground.toString() : null; - this.feedbackForm.style.boxShadow = colors.widgetShadow ? `0 0 8px ${colors.widgetShadow}` : null; + this.feedbackForm.style.boxShadow = colors.widgetShadow ? `0 0 8px ${colors.widgetShadow}` : ''; } if (this.feedbackDescriptionInput) { - this.feedbackDescriptionInput.style.backgroundColor = colors.inputBackground ? colors.inputBackground.toString() : null; + this.feedbackDescriptionInput.style.backgroundColor = colors.inputBackground ? colors.inputBackground.toString() : ''; this.feedbackDescriptionInput.style.color = colors.inputForeground ? colors.inputForeground.toString() : null; this.feedbackDescriptionInput.style.border = `1px solid ${colors.inputBorder || 'transparent'}`; } - contactUsContainer.style.backgroundColor = colors.editorBackground ? colors.editorBackground.toString() : null; + contactUsContainer.style.backgroundColor = colors.editorBackground ? colors.editorBackground.toString() : ''; contactUsContainer.style.border = `1px solid ${colors.contrastBorder || 'transparent'}`; })); diff --git a/src/vs/workbench/contrib/markers/browser/markersPanelActions.ts b/src/vs/workbench/contrib/markers/browser/markersPanelActions.ts index b2498c05d82..cfba514af3f 100644 --- a/src/vs/workbench/contrib/markers/browser/markersPanelActions.ts +++ b/src/vs/workbench/contrib/markers/browser/markersPanelActions.ts @@ -196,14 +196,14 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { private createBadge(container: HTMLElement): void { const filterBadge = this.filterBadge = DOM.append(container, DOM.$('.markers-panel-filter-badge')); this._register(attachStylerCallback(this.themeService, { badgeBackground, badgeForeground, contrastBorder }, colors => { - const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; - const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : null; - const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; + const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; + const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : ''; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : ''; filterBadge.style.backgroundColor = background; - filterBadge.style.borderWidth = border ? '1px' : null; - filterBadge.style.borderStyle = border ? 'solid' : null; + filterBadge.style.borderWidth = border ? '1px' : ''; + filterBadge.style.borderStyle = border ? 'solid' : ''; filterBadge.style.borderColor = border; filterBadge.style.color = foreground; })); From 2b4638e1acdc9ddb0f89fe7a4a8c0727c5153e01 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 5 Oct 2019 14:37:32 -0700 Subject: [PATCH 238/435] Fix missing function calls in condition --- extensions/css-language-features/server/src/cssServerMain.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index 0856a649326..7cf07998b1e 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -75,9 +75,9 @@ const fileSystemProvider: FileSystemProvider = { let type = FileType.Unknown; if (stats.isFile()) { type = FileType.File; - } else if (stats.isDirectory) { + } else if (stats.isDirectory()) { type = FileType.Directory; - } else if (stats.isSymbolicLink) { + } else if (stats.isSymbolicLink()) { type = FileType.SymbolicLink; } From 4c4edcefebbf7286a78778ef23f81b90f53dace3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Sat, 5 Oct 2019 14:54:53 -0700 Subject: [PATCH 239/435] Fixing more TS 3.7 related compile errors - Import aliasing symbol in file - Missing function calls in conditional - Missing return statement --- extensions/git/src/util.ts | 2 +- src/vs/base/browser/ui/grid/grid.ts | 1 - src/vs/base/parts/ipc/common/ipc.ts | 1 - src/vs/editor/browser/controller/mouseTarget.ts | 2 +- src/vs/editor/browser/editorExtensions.ts | 14 +++++++------- .../editor/common/modes/languageConfiguration.ts | 2 +- src/vs/workbench/common/views.ts | 1 - src/vs/workbench/contrib/files/common/files.ts | 4 ++-- .../electron-browser/workspaceEditingService.ts | 2 ++ 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index d2e201ca01d..0722cb16fbd 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -160,7 +160,7 @@ export async function mkdirp(path: string, mode?: number): Promise { if (err.code === 'EEXIST') { const stat = await nfcall(fs.stat, path); - if (stat.isDirectory) { + if (stat.isDirectory()) { return; } diff --git a/src/vs/base/browser/ui/grid/grid.ts b/src/vs/base/browser/ui/grid/grid.ts index 28b184f76d9..c2448a2fbff 100644 --- a/src/vs/base/browser/ui/grid/grid.ts +++ b/src/vs/base/browser/ui/grid/grid.ts @@ -9,7 +9,6 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { tail2 as tail, equals } from 'vs/base/common/arrays'; import { orthogonal, IView as IGridViewView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles, IViewSize, IGridViewOptions } from './gridview'; import { Event } from 'vs/base/common/event'; -import { InvisibleSizing } from 'vs/base/browser/ui/splitview/splitview'; export { Orientation, Sizing as GridViewSizing, IViewSize, orthogonal, LayoutPriority } from './gridview'; diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 7b60ba4a101..48f75577206 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -8,7 +8,6 @@ import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/li import { CancelablePromise, createCancelablePromise, timeout } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import * as errors from 'vs/base/common/errors'; -import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc'; import { VSBuffer } from 'vs/base/common/buffer'; /** diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index c025c958a0f..c396ab9b09d 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -972,7 +972,7 @@ export class MouseTargetFactory { // Thank you browsers for making this so 'easy' :) - if (document.caretRangeFromPoint) { + if (typeof document.caretRangeFromPoint === 'function') { return this._doHitTestWithCaretRangeFromPoint(ctx, request); diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index c467768414b..ffccc8832bd 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -16,17 +16,17 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IConstructorSignature1, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { withNullAsUndefined } from 'vs/base/common/types'; -export type ServicesAccessor = ServicesAccessor; +export type ServicesAccessor = InstantiationServicesAccessor; export type IEditorContributionCtor = IConstructorSignature1; export type EditorTelemetryDataFragment = { - target: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - snippet: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; + target: { classification: 'SystemMetaData', purpose: 'FeatureInsight', }; + snippet: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true, }; }; //#region Command @@ -224,8 +224,8 @@ export abstract class EditorAction extends EditorCommand { protected reportTelemetry(accessor: ServicesAccessor, editor: ICodeEditor) { type EditorActionInvokedClassification = { - name: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - id: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + name: { classification: 'SystemMetaData', purpose: 'FeatureInsight', }; + id: { classification: 'SystemMetaData', purpose: 'FeatureInsight', }; }; type EditorActionInvokedEvent = { name: string; @@ -241,7 +241,7 @@ export abstract class EditorAction extends EditorCommand { // --- Registration of commands and actions -export function registerLanguageCommand(id: string, handler: (accessor: ServicesAccessor, args: Args) => any) { +export function registerLanguageCommand(id: string, handler: (accessor: ServicesAccessor, args: Args) => any) { CommandsRegistry.registerCommand(id, (accessor, args) => handler(accessor, args || {})); } diff --git a/src/vs/editor/common/modes/languageConfiguration.ts b/src/vs/editor/common/modes/languageConfiguration.ts index ed8d2fdb4ae..686c7a0dab2 100644 --- a/src/vs/editor/common/modes/languageConfiguration.ts +++ b/src/vs/editor/common/modes/languageConfiguration.ts @@ -247,7 +247,7 @@ export class StandardAutoClosingPairConditional { if (Array.isArray(source.notIn)) { for (let i = 0, len = source.notIn.length; i < len; i++) { - let notIn = source.notIn[i]; + const notIn: string = source.notIn[i]; switch (notIn) { case 'string': this._standardTokenMask |= StandardTokenType.String; diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 6a4147042e3..2e733ef117c 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -7,7 +7,6 @@ import { Command } from 'vs/editor/common/modes'; import { UriComponents } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { ITreeViewDataProvider } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 8f5470bff77..a55bbfa8ed4 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IWorkbenchEditorConfiguration, IEditorIdentifier, IEditorInput, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; -import { IFilesConfiguration, FileChangeType, IFileService } from 'vs/platform/files/common/files'; +import { IFilesConfiguration as PlatformIFilesConfiguration, FileChangeType, IFileService } from 'vs/platform/files/common/files'; import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; @@ -102,7 +102,7 @@ export const FILE_EDITOR_INPUT_ID = 'workbench.editors.files.fileEditorInput'; export const BINARY_FILE_EDITOR_ID = 'workbench.editors.files.binaryFileEditor'; -export interface IFilesConfiguration extends IFilesConfiguration, IWorkbenchEditorConfiguration { +export interface IFilesConfiguration extends PlatformIFilesConfiguration, IWorkbenchEditorConfiguration { explorer: { openEditors: { visible: number; diff --git a/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts index 5c983b207b1..bc5c69825bd 100644 --- a/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts @@ -142,6 +142,8 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi return false; } } + + return false; } async isValidTargetWorkspacePath(path: URI): Promise { From 6869239fd805221a59dde40fadfa55447321ca57 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 20:33:16 +0200 Subject: [PATCH 240/435] :up: terser@4.3.8 (#82057) --- build/package.json | 2 +- build/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/package.json b/build/package.json index bf3ec5ce3f9..84556e6e17d 100644 --- a/build/package.json +++ b/build/package.json @@ -40,7 +40,7 @@ "mime": "^1.3.4", "minimist": "^1.2.0", "request": "^2.85.0", - "terser": "4.3.1", + "terser": "4.3.8", "tslint": "^5.9.1", "typescript": "3.6.2", "vsce": "1.48.0", diff --git a/build/yarn.lock b/build/yarn.lock index 937eb1daa43..2451df9b537 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -2178,10 +2178,10 @@ terser@*: source-map "~0.6.1" source-map-support "~0.5.12" -terser@4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" - integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== +terser@4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.8.tgz#707f05f3f4c1c70c840e626addfdb1c158a17136" + integrity sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ== dependencies: commander "^2.20.0" source-map "~0.6.1" From 3c70da4c8ccbc6f001ea1d04743a7ed7b44fb3ed Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Oct 2019 20:33:35 +0200 Subject: [PATCH 241/435] :up: graceful-fs@4.2.2 (#82058) --- package.json | 4 ++-- remote/package.json | 2 +- remote/yarn.lock | 7 ++++++- yarn.lock | 7 ++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fbeb6d1e659..72578602b1a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@microsoft/applicationinsights-web": "^2.1.1", "applicationinsights": "1.0.8", "chokidar": "3.1.0", - "graceful-fs": "4.1.11", + "graceful-fs": "4.2.2", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "iconv-lite": "0.5.0", @@ -153,4 +153,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} diff --git a/remote/package.json b/remote/package.json index 10c377499f1..603799a71ea 100644 --- a/remote/package.json +++ b/remote/package.json @@ -6,7 +6,7 @@ "applicationinsights": "1.0.8", "chokidar": "3.1.0", "cookie": "^0.4.0", - "graceful-fs": "4.1.11", + "graceful-fs": "4.2.2", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "iconv-lite": "0.5.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index 052c1fa7847..7538d4adfe0 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -211,7 +211,12 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -graceful-fs@4.1.11, graceful-fs@^4.1.2: +graceful-fs@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= diff --git a/yarn.lock b/yarn.lock index 4304721fc4d..2e1a8d76c61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3568,7 +3568,12 @@ glogg@^1.0.0: dependencies: sparkles "^1.0.0" -graceful-fs@4.1.11, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= From 73d2f81d13e6a9508d9896f0e75493d9ddae8ab3 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 7 Oct 2019 13:33:00 -0700 Subject: [PATCH 242/435] Mark that pendingComment can be null, #81574 --- .../workbench/contrib/comments/browser/commentThreadWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 09438e54175..a58e626db11 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -100,7 +100,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget editor: ICodeEditor, private _owner: string, private _commentThread: modes.CommentThread, - private _pendingComment: string, + private _pendingComment: string | null, @IInstantiationService private instantiationService: IInstantiationService, @IModeService private modeService: IModeService, @IModelService private modelService: IModelService, From a660620e880b558def1b69677d09c73b8ca8abc0 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:05:58 -0700 Subject: [PATCH 243/435] Convert null -> undefined --- src/vs/platform/configuration/common/configurationModels.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index c4749186815..7750ef0b32d 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -518,14 +518,14 @@ export class Configuration { return folderConsolidatedConfiguration; } - private getFolderConfigurationModelForResource(resource: URI | null | undefined, workspace: Workspace | undefined): ConfigurationModel | null { + private getFolderConfigurationModelForResource(resource: URI | null | undefined, workspace: Workspace | undefined): ConfigurationModel | undefined { if (workspace && resource) { const root = workspace.getFolder(resource); if (root) { - return types.withUndefinedAsNull(this._folderConfigurations.get(root.uri)); + return this._folderConfigurations.get(root.uri); } } - return null; + return undefined; } toData(): IConfigurationData { From 02ae385856b95d322f2b55d61af57bc224957215 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:09:33 -0700 Subject: [PATCH 244/435] Convert getPanel to return undefined instead of null --- src/vs/workbench/browser/composite.ts | 8 ++++---- src/vs/workbench/browser/panel.ts | 2 +- src/vs/workbench/browser/parts/panel/panelPart.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index 38dde654626..fdbd1478f1b 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -258,7 +258,7 @@ export abstract class CompositeRegistry extends Disposable private composites: CompositeDescriptor[] = []; protected registerComposite(descriptor: CompositeDescriptor): void { - if (this.compositeById(descriptor.id) !== null) { + if (this.compositeById(descriptor.id)) { return; } @@ -276,7 +276,7 @@ export abstract class CompositeRegistry extends Disposable this._onDidDeregister.fire(descriptor); } - getComposite(id: string): CompositeDescriptor | null { + getComposite(id: string): CompositeDescriptor | undefined { return this.compositeById(id); } @@ -284,13 +284,13 @@ export abstract class CompositeRegistry extends Disposable return this.composites.slice(0); } - private compositeById(id: string): CompositeDescriptor | null { + private compositeById(id: string): CompositeDescriptor | undefined { for (const composite of this.composites) { if (composite.id === id) { return composite; } } - return null; + return undefined; } } diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index 35da00194aa..b4cbfb337cc 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -45,7 +45,7 @@ export class PanelRegistry extends CompositeRegistry { /** * Returns a panel by id. */ - getPanel(id: string): PanelDescriptor | null { + getPanel(id: string): PanelDescriptor | undefined { return this.getComposite(id); } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 4015b6dffc7..5a506ee3d8f 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -30,7 +30,7 @@ import { Dimension, trackFocus } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, withUndefinedAsNull, withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; +import { isUndefinedOrNull, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -241,7 +241,7 @@ export class PanelPart extends CompositePart implements IPanelService { } getPanel(panelId: string): IPanelIdentifier | undefined { - return withNullAsUndefined(Registry.as(PanelExtensions.Panels).getPanel(panelId)); + return Registry.as(PanelExtensions.Panels).getPanel(panelId); } getPanels(): PanelDescriptor[] { From ab3f2e6180dbfce96bf16917103a1c07e4abbae2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:10:23 -0700 Subject: [PATCH 245/435] Use find instead of for loop --- src/vs/workbench/browser/composite.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index fdbd1478f1b..6414496a6d3 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -15,6 +15,7 @@ import { trackFocus, Dimension } from 'vs/base/browser/dom'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { Disposable } from 'vs/base/common/lifecycle'; import { assertIsDefined } from 'vs/base/common/types'; +import { find } from 'vs/base/common/arrays'; /** * Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite @@ -285,12 +286,6 @@ export abstract class CompositeRegistry extends Disposable } private compositeById(id: string): CompositeDescriptor | undefined { - for (const composite of this.composites) { - if (composite.id === id) { - return composite; - } - } - - return undefined; + return find(this.composites, composite => composite.id === id); } } From de9a8a67b3f7a9a13799a6cb568399cf870ee638 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:18:32 -0700 Subject: [PATCH 246/435] Converting some parts of panel service to return undefined instead of null --- src/vs/workbench/browser/parts/compositePart.ts | 7 +++---- src/vs/workbench/browser/parts/panel/panelPart.ts | 10 +++++----- .../workbench/contrib/output/browser/outputServices.ts | 2 +- src/vs/workbench/services/panel/common/panelService.ts | 4 ++-- .../api/mainThreadDocumentsAndEditors.test.ts | 2 +- .../electron-browser/api/mainThreadEditors.test.ts | 2 +- src/vs/workbench/test/workbenchTestServices.ts | 4 ++-- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 1058b69e765..c71cbac2538 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -61,7 +61,7 @@ export abstract class CompositePart extends Part { private mapCompositeToCompositeContainer = new Map(); private mapActionsBindingToComposite = new Map void>(); - private activeComposite: Composite | null; + private activeComposite: Composite | undefined; private lastActiveCompositeId: string; private instantiatedCompositeItems: Map; private titleLabel: ICompositeTitleLabel; @@ -90,7 +90,6 @@ export abstract class CompositePart extends Part { ) { super(id, options, themeService, storageService, layoutService); - this.activeComposite = null; this.instantiatedCompositeItems = new Map(); this.lastActiveCompositeId = storageService.get(activeCompositeSettingsKey, StorageScope.WORKSPACE, this.defaultCompositeId); } @@ -332,7 +331,7 @@ export abstract class CompositePart extends Part { return this.toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions)); } - protected getActiveComposite(): IComposite | null { + protected getActiveComposite(): IComposite | undefined { return this.activeComposite; } @@ -346,7 +345,7 @@ export abstract class CompositePart extends Part { } const composite = this.activeComposite; - this.activeComposite = null; + this.activeComposite = undefined; const compositeContainer = this.mapCompositeToCompositeContainer.get(composite.getId()); diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 5a506ee3d8f..dcf2ea48930 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -30,7 +30,7 @@ import { Dimension, trackFocus } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types'; +import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -218,9 +218,9 @@ export class PanelPart extends CompositePart implements IPanelService { } } - openPanel(id: string, focus?: boolean): Panel | null { + openPanel(id: string, focus?: boolean): Panel | undefined { if (this.blockOpeningPanel) { - return null; // Workaround against a potential race condition + return undefined; // Workaround against a potential race condition } // First check if panel is hidden and show if so @@ -233,7 +233,7 @@ export class PanelPart extends CompositePart implements IPanelService { } } - return withUndefinedAsNull(this.openComposite(id, focus)); + return this.openComposite(id, focus); } showActivity(panelId: string, badge: IBadge, clazz?: string): IDisposable { @@ -263,7 +263,7 @@ export class PanelPart extends CompositePart implements IPanelService { ]; } - getActivePanel(): IPanel | null { + getActivePanel(): IPanel | undefined { return this.getActiveComposite(); } diff --git a/src/vs/workbench/contrib/output/browser/outputServices.ts b/src/vs/workbench/contrib/output/browser/outputServices.ts index 1a3e692d6e7..940441708e4 100644 --- a/src/vs/workbench/contrib/output/browser/outputServices.ts +++ b/src/vs/workbench/contrib/output/browser/outputServices.ts @@ -155,7 +155,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo } } - private onDidPanelOpen(panel: IPanel | null, preserveFocus: boolean): Promise { + private onDidPanelOpen(panel: IPanel | undefined, preserveFocus: boolean): Promise { if (panel && panel.getId() === OUTPUT_PANEL_ID) { this._outputPanel = this.panelService.getActivePanel(); if (this.activeChannel) { diff --git a/src/vs/workbench/services/panel/common/panelService.ts b/src/vs/workbench/services/panel/common/panelService.ts index d686236e30a..2e16224d988 100644 --- a/src/vs/workbench/services/panel/common/panelService.ts +++ b/src/vs/workbench/services/panel/common/panelService.ts @@ -28,12 +28,12 @@ export interface IPanelService { /** * Opens a panel with the given identifier and pass keyboard focus to it if specified. */ - openPanel(id: string, focus?: boolean): IPanel | null; + openPanel(id: string, focus?: boolean): IPanel | undefined; /** * Returns the current active panel or null if none */ - getActivePanel(): IPanel | null; + getActivePanel(): IPanel | undefined; /** * Returns the panel by id. diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts index aa5453e5f6c..483d634e6ea 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts @@ -79,7 +79,7 @@ suite('MainThreadDocumentsAndEditors', () => { onDidPanelOpen = Event.None; onDidPanelClose = Event.None; getActivePanel() { - return null; + return undefined; } }, TestEnvironmentService diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts index bd1397d06fb..35fde4c61de 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts @@ -111,7 +111,7 @@ suite('MainThreadEditors', () => { onDidPanelOpen = Event.None; onDidPanelClose = Event.None; getActivePanel() { - return null; + return undefined; } }, TestEnvironmentService diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 19f35faaeaf..bdb10705c62 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -626,8 +626,8 @@ export class TestPanelService implements IPanelService { onDidPanelOpen = new Emitter<{ panel: IPanel, focus: boolean }>().event; onDidPanelClose = new Emitter().event; - public openPanel(id: string, focus?: boolean): IPanel { - return null!; + public openPanel(id: string, focus?: boolean): undefined { + return undefined; } public getPanel(id: string): any { From 948af79e4942ad9fd8de9de0199ad7f7b4811cdc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:20:31 -0700 Subject: [PATCH 247/435] Markding results from panelService as readonly --- src/vs/workbench/browser/parts/panel/panelPart.ts | 4 ++-- src/vs/workbench/services/panel/common/panelService.ts | 6 +++--- src/vs/workbench/test/workbenchTestServices.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index dcf2ea48930..651d4254d39 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -244,12 +244,12 @@ export class PanelPart extends CompositePart implements IPanelService { return Registry.as(PanelExtensions.Panels).getPanel(panelId); } - getPanels(): PanelDescriptor[] { + getPanels(): readonly PanelDescriptor[] { return Registry.as(PanelExtensions.Panels).getPanels() .sort((v1, v2) => typeof v1.order === 'number' && typeof v2.order === 'number' ? v1.order - v2.order : NaN); } - getPinnedPanels(): PanelDescriptor[] { + getPinnedPanels(): readonly PanelDescriptor[] { const pinnedCompositeIds = this.compositeBar.getPinnedComposites().map(c => c.id); return this.getPanels() .filter(p => pinnedCompositeIds.indexOf(p.id) !== -1) diff --git a/src/vs/workbench/services/panel/common/panelService.ts b/src/vs/workbench/services/panel/common/panelService.ts index 2e16224d988..13d6a6b54e6 100644 --- a/src/vs/workbench/services/panel/common/panelService.ts +++ b/src/vs/workbench/services/panel/common/panelService.ts @@ -22,7 +22,7 @@ export interface IPanelService { _serviceBrand: undefined; - readonly onDidPanelOpen: Event<{ panel: IPanel, focus: boolean }>; + readonly onDidPanelOpen: Event<{ readonly panel: IPanel, readonly focus: boolean }>; readonly onDidPanelClose: Event; /** @@ -43,12 +43,12 @@ export interface IPanelService { /** * Returns all built-in panels following the default order */ - getPanels(): IPanelIdentifier[]; + getPanels(): readonly IPanelIdentifier[]; /** * Returns pinned panels following the visual order */ - getPinnedPanels(): IPanelIdentifier[]; + getPinnedPanels(): readonly IPanelIdentifier[]; /** * Returns the progress indicator for the panel bar. diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index bdb10705c62..f85d68fb3b7 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -634,11 +634,11 @@ export class TestPanelService implements IPanelService { return activeViewlet; } - public getPanels(): any[] { + public getPanels() { return []; } - public getPinnedPanels(): any[] { + public getPinnedPanels() { return []; } From 4a461d267f6a63a776e21d28465b517890d43242 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:27:03 -0700 Subject: [PATCH 248/435] Converting a few functions in ITokenizationRegistry to return undefined instead of null --- .../electron-browser/issue/issueReporterMain.ts | 3 +-- src/vs/editor/common/model/textModelTokens.ts | 9 ++++----- src/vs/editor/common/modes.ts | 8 ++++---- .../editor/common/modes/tokenizationRegistry.ts | 17 ++++++----------- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index c65686451de..3191cdc737a 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -37,7 +37,6 @@ import { ILogService, getLogLevel } from 'vs/platform/log/common/log'; import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import { normalizeGitHubUrl } from 'vs/code/electron-browser/issue/issueReporterUtil'; import { Button } from 'vs/base/browser/ui/button/button'; -import { withUndefinedAsNull } from 'vs/base/common/types'; import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; @@ -232,7 +231,7 @@ export class IssueReporter extends Disposable { styleTag.innerHTML = content.join('\n'); document.head.appendChild(styleTag); - document.body.style.color = withUndefinedAsNull(styles.color); + document.body.style.color = styles.color || ''; } private handleExtensionData(extensions: IssueReporterExtensionData[]) { diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index 03e1c4bd6b7..7749d45b6ad 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -197,14 +197,13 @@ export class TextModelTokenization extends Disposable { private readonly _textModel: TextModel; private readonly _tokenizationStateStore: TokenizationStateStore; private _revalidateTokensTimeout: any; - private _tokenizationSupport: ITokenizationSupport | null; + private _tokenizationSupport: ITokenizationSupport | undefined; constructor(textModel: TextModel) { super(); this._textModel = textModel; this._tokenizationStateStore = new TokenizationStateStore(); this._revalidateTokensTimeout = -1; - this._tokenizationSupport = null; this._register(TokenizationRegistry.onDidChange((e) => { const languageIdentifier = this._textModel.getLanguageIdentifier(); @@ -428,11 +427,11 @@ export class TextModelTokenization extends Disposable { } } -function initializeTokenization(textModel: TextModel): [ITokenizationSupport | null, IState | null] { +function initializeTokenization(textModel: TextModel): [ITokenizationSupport | undefined, IState | null] { const languageIdentifier = textModel.getLanguageIdentifier(); let tokenizationSupport = ( textModel.isTooLargeForTokenization() - ? null + ? undefined : TokenizationRegistry.get(languageIdentifier.language) ); let initialState: IState | null = null; @@ -441,7 +440,7 @@ function initializeTokenization(textModel: TextModel): [ITokenizationSupport | n initialState = tokenizationSupport.getInitialState(); } catch (e) { onUnexpectedError(e); - tokenizationSupport = null; + tokenizationSupport = undefined; } } return [tokenizationSupport, initialState]; diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index ede4308bd87..70feadc2677 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1568,9 +1568,9 @@ export interface ITokenizationRegistry { /** * Get the tokenization support for a language. - * Returns `null` if not found. + * Returns `undefined` if not found. */ - get(language: string): ITokenizationSupport | null; + get(language: string): ITokenizationSupport | undefined; /** * Get the promise of a tokenization support for a language. @@ -1583,9 +1583,9 @@ export interface ITokenizationRegistry { */ setColorMap(colorMap: Color[]): void; - getColorMap(): Color[] | null; + getColorMap(): Color[] | undefined; - getDefaultBackground(): Color | null; + getDefaultBackground(): Color | undefined; } /** diff --git a/src/vs/editor/common/modes/tokenizationRegistry.ts b/src/vs/editor/common/modes/tokenizationRegistry.ts index fc3423047fb..d1492e39107 100644 --- a/src/vs/editor/common/modes/tokenizationRegistry.ts +++ b/src/vs/editor/common/modes/tokenizationRegistry.ts @@ -7,7 +7,6 @@ import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes'; -import { withUndefinedAsNull } from 'vs/base/common/types'; import { keys } from 'vs/base/common/map'; export class TokenizationRegistryImpl implements ITokenizationRegistry { @@ -18,11 +17,7 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { private readonly _onDidChange = new Emitter(); public readonly onDidChange: Event = this._onDidChange.event; - private _colorMap: Color[] | null; - - constructor() { - this._colorMap = null; - } + private _colorMap: Color[] | undefined; public fire(languages: string[]): void { this._onDidChange.fire({ @@ -76,8 +71,8 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { return null; } - public get(language: string): ITokenizationSupport | null { - return withUndefinedAsNull(this._map.get(language)); + public get(language: string): ITokenizationSupport | undefined { + return this._map.get(language); } public setColorMap(colorMap: Color[]): void { @@ -88,14 +83,14 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { }); } - public getColorMap(): Color[] | null { + public getColorMap(): Color[] | undefined { return this._colorMap; } - public getDefaultBackground(): Color | null { + public getDefaultBackground(): Color | undefined { if (this._colorMap && this._colorMap.length > ColorId.DefaultBackground) { return this._colorMap[ColorId.DefaultBackground]; } - return null; + return undefined; } } From 6e593ab812301d2e399693f80e72c1d3f9311055 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 11:50:34 -0700 Subject: [PATCH 249/435] Converting some search for loops to use .some/.every instead Prefer using these predicates as they are shorter and make the code easier to understand --- src/vs/workbench/browser/actions.ts | 8 +------- .../browser/languageConfigurationExtensionPoint.ts | 11 +---------- .../extensions/common/extensionDescriptionRegistry.ts | 7 +------ .../services/extensions/common/rpcProtocol.ts | 7 +------ .../services/extensions/node/extensionPoints.ts | 10 +--------- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/browser/actions.ts b/src/vs/workbench/browser/actions.ts index 6e9909e2633..2cf27b60ae6 100644 --- a/src/vs/workbench/browser/actions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -57,13 +57,7 @@ export class ContributableActionProvider implements IActionProvider { const context = this.toContext(tree, element); const contributors = this.registry.getActionBarContributors(Scope.VIEWER); - for (const contributor of contributors) { - if (contributor.hasActions(context)) { - return true; - } - } - - return false; + return contributors.some(contributor => contributor.hasActions(context)); } getActions(tree: ITree, element: unknown): ReadonlyArray { diff --git a/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts b/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts index 558d193d12a..b0f4b9c4894 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts @@ -43,16 +43,7 @@ interface ILanguageConfiguration { } function isStringArr(something: string[] | null): something is string[] { - 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; - + return Array.isArray(something) && something.every(value => typeof value === 'string'); } function isCharacterPair(something: CharacterPair | null): boolean { diff --git a/src/vs/workbench/services/extensions/common/extensionDescriptionRegistry.ts b/src/vs/workbench/services/extensions/common/extensionDescriptionRegistry.ts index 38c4b63eda7..ab3477a4fc7 100644 --- a/src/vs/workbench/services/extensions/common/extensionDescriptionRegistry.ts +++ b/src/vs/workbench/services/extensions/common/extensionDescriptionRegistry.ts @@ -118,12 +118,7 @@ export class ExtensionDescriptionRegistry { hasOnlyGoodArcs(id: string, good: Set): boolean { const dependencies = G.getArcs(id); - for (let i = 0; i < dependencies.length; i++) { - if (!good.has(dependencies[i])) { - return false; - } - } - return true; + return dependencies.every(dependency => good.has(dependency)); } getNodes(): string[] { diff --git a/src/vs/workbench/services/extensions/common/rpcProtocol.ts b/src/vs/workbench/services/extensions/common/rpcProtocol.ts index ab46c17ec1e..7748ca5edbd 100644 --- a/src/vs/workbench/services/extensions/common/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/common/rpcProtocol.ts @@ -588,12 +588,7 @@ class MessageBuffer { class MessageIO { private static _arrayContainsBuffer(arr: any[]): boolean { - for (let i = 0, len = arr.length; i < len; i++) { - if (arr[i] instanceof VSBuffer) { - return true; - } - } - return false; + return arr.some(value => value instanceof VSBuffer); } public static serializeRequest(req: number, rpcId: number, method: string, args: any[], usesCancellationToken: boolean, replacer: JSONStringifyReplacer | null): VSBuffer { diff --git a/src/vs/workbench/services/extensions/node/extensionPoints.ts b/src/vs/workbench/services/extensions/node/extensionPoints.ts index 4d08f7645a0..17fdf323c7c 100644 --- a/src/vs/workbench/services/extensions/node/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/node/extensionPoints.ts @@ -393,15 +393,7 @@ class ExtensionManifestValidator extends ExtensionManifestHandler { } private static _isStringArray(arr: string[]): boolean { - if (!Array.isArray(arr)) { - return false; - } - for (let i = 0, len = arr.length; i < len; i++) { - if (typeof arr[i] !== 'string') { - return false; - } - } - return true; + return Array.isArray(arr) && arr.every(value => typeof value === 'string'); } } From 40e0f496f97bd655f114d25084dc4a7b88b81299 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 14:13:18 -0700 Subject: [PATCH 250/435] Use equals helper function instead of re-implementing it so many places --- src/vs/base/common/keyCodes.ts | 11 ++------ src/vs/editor/common/core/selection.ts | 11 ++------ .../common/viewLayout/lineDecorations.ts | 15 +++-------- .../common/viewLayout/viewLineRenderer.ts | 13 ++-------- .../editor/contrib/cursorUndo/cursorUndo.ts | 13 ++-------- .../editor/test/common/core/viewLineToken.ts | 15 +++-------- .../platform/contextkey/common/contextkey.ts | 21 +++------------- .../watcher/unix/chokidarWatcherService.ts | 13 +++------- .../workbench/api/browser/mainThreadEditor.ts | 25 ++++--------------- .../api/common/extHostDocumentData.ts | 14 +++-------- src/vs/workbench/api/common/extHostSCM.ts | 16 +++--------- .../browser/keybindingsEditorContribution.ts | 14 ++--------- 12 files changed, 33 insertions(+), 148 deletions(-) diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index ec08bea7e91..98ac19e0843 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -5,6 +5,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; import { illegalArgument } from 'vs/base/common/errors'; +import { equals } from 'vs/base/common/arrays'; /** * Virtual Key Codes, the value does not hold any inherent meaning. @@ -525,15 +526,7 @@ export class ChordKeybinding { if (other === null) { return false; } - if (this.parts.length !== other.parts.length) { - return false; - } - for (let i = 0; i < this.parts.length; i++) { - if (!this.parts[i].equals(other.parts[i])) { - return false; - } - } - return true; + return equals(this.parts, other.parts, (a, b) => a.equals(b)); } } diff --git a/src/vs/editor/common/core/selection.ts b/src/vs/editor/common/core/selection.ts index 80143cdf97a..b1776654e94 100644 --- a/src/vs/editor/common/core/selection.ts +++ b/src/vs/editor/common/core/selection.ts @@ -5,6 +5,7 @@ import { IPosition, Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; +import { equals } from 'vs/base/common/arrays'; /** * A selection in the editor. @@ -171,15 +172,7 @@ export class Selection extends Range { if (!a && !b) { return true; } - if (a.length !== b.length) { - return false; - } - for (let i = 0, len = a.length; i < len; i++) { - if (!this.selectionsEqual(a[i], b[i])) { - return false; - } - } - return true; + return equals(a, b, this.selectionsEqual); } /** diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index 5e79341a942..cae03bc9e46 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -6,6 +6,7 @@ import * as strings from 'vs/base/common/strings'; import { Constants } from 'vs/editor/common/core/uint'; import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; +import { equals } from 'vs/base/common/arrays'; export class LineDecoration { _lineDecorationBrand: void; @@ -27,18 +28,8 @@ export class LineDecoration { ); } - public static equalsArr(a: LineDecoration[], b: LineDecoration[]): boolean { - let aLen = a.length; - let bLen = b.length; - if (aLen !== bLen) { - return false; - } - for (let i = 0; i < aLen; i++) { - if (!LineDecoration._equals(a[i], b[i])) { - return false; - } - } - return true; + public static equalsArr(a: readonly LineDecoration[], b: readonly LineDecoration[]): boolean { + return equals(a, b, LineDecoration._equals); } public static filter(lineDecorations: InlineDecoration[], lineNumber: number, minLineColumn: number, maxLineColumn: number): LineDecoration[] { diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index bbb9b39cb8c..0b41b006f65 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -9,6 +9,7 @@ import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder'; import { LineDecoration, LineDecorationsNormalizer } from 'vs/editor/common/viewLayout/lineDecorations'; import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; +import { equals } from 'vs/base/common/arrays'; export const enum RenderWhitespace { None = 0, @@ -131,17 +132,7 @@ export class RenderLineInput { return false; } - if (otherSelections.length !== this.selectionsOnLine.length) { - return false; - } - - for (let i = 0; i < this.selectionsOnLine.length; i++) { - if (!this.selectionsOnLine[i].equals(otherSelections[i])) { - return false; - } - } - - return true; + return equals(this.selectionsOnLine, otherSelections, (a, b) => a.equals(b)); } public equals(other: RenderLineInput): boolean { diff --git a/src/vs/editor/contrib/cursorUndo/cursorUndo.ts b/src/vs/editor/contrib/cursorUndo/cursorUndo.ts index 0d9ea4ea21e..e4568052f62 100644 --- a/src/vs/editor/contrib/cursorUndo/cursorUndo.ts +++ b/src/vs/editor/contrib/cursorUndo/cursorUndo.ts @@ -12,6 +12,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { equals } from 'vs/base/common/arrays'; class CursorState { readonly selections: readonly Selection[]; @@ -21,17 +22,7 @@ class CursorState { } public equals(other: CursorState): boolean { - const thisLen = this.selections.length; - const otherLen = other.selections.length; - if (thisLen !== otherLen) { - return false; - } - for (let i = 0; i < thisLen; i++) { - if (!this.selections[i].equalsSelection(other.selections[i])) { - return false; - } - } - return true; + return equals(this.selections, other.selections, (a, b) => a.equalsSelection(b)); } } diff --git a/src/vs/editor/test/common/core/viewLineToken.ts b/src/vs/editor/test/common/core/viewLineToken.ts index 340157110ae..d91fe77bcf0 100644 --- a/src/vs/editor/test/common/core/viewLineToken.ts +++ b/src/vs/editor/test/common/core/viewLineToken.ts @@ -5,6 +5,7 @@ import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { ColorId, TokenMetadata } from 'vs/editor/common/modes'; +import { equals } from 'vs/base/common/arrays'; /** * A token on a line. @@ -42,18 +43,8 @@ export class ViewLineToken { ); } - public static equalsArr(a: ViewLineToken[], b: ViewLineToken[]): boolean { - const aLen = a.length; - const bLen = b.length; - if (aLen !== bLen) { - return false; - } - for (let i = 0; i < aLen; i++) { - if (!this._equals(a[i], b[i])) { - return false; - } - } - return true; + public static equalsArr(a: readonly ViewLineToken[], b: readonly ViewLineToken[]): boolean { + return equals(a, b, this._equals); } } diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 16e79df476f..ed418e1d89f 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -6,6 +6,7 @@ import { Event } from 'vs/base/common/event'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { equals } from 'vs/base/common/arrays'; export const enum ContextKeyExprType { Defined = 1, @@ -574,15 +575,7 @@ export class ContextKeyAndExpr implements ContextKeyExpr { public equals(other: ContextKeyExpr): boolean { if (other instanceof ContextKeyAndExpr) { - if (this.expr.length !== other.expr.length) { - return false; - } - for (let i = 0, len = this.expr.length; i < len; i++) { - if (!this.expr[i].equals(other.expr[i])) { - return false; - } - } - return true; + return equals(this.expr, other.expr, (a, b) => a.equals(b)); } return false; } @@ -674,15 +667,7 @@ export class ContextKeyOrExpr implements ContextKeyExpr { public equals(other: ContextKeyExpr): boolean { if (other instanceof ContextKeyOrExpr) { - if (this.expr.length !== other.expr.length) { - return false; - } - for (let i = 0, len = this.expr.length; i < len; i++) { - if (!this.expr[i].equals(other.expr[i])) { - return false; - } - } - return true; + return equals(this.expr, other.expr, (a, b) => a.equals(b)); } return false; } diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index d129ec844a9..bd4632e1915 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -17,6 +17,7 @@ import { isMacintosh, isLinux } from 'vs/base/common/platform'; import { IDiskFileChange, normalizeFileChanges, ILogMessage } from 'vs/platform/files/node/watcher/watcher'; import { IWatcherRequest, IWatcherService, IWatcherOptions } from 'vs/platform/files/node/watcher/unix/watcher'; import { Emitter, Event } from 'vs/base/common/event'; +import { equals } from 'vs/base/common/arrays'; interface IWatcher { requests: ExtendedWatcherRequest[]; @@ -363,14 +364,6 @@ function isEqualRequests(r1: IWatcherRequest[], r2: IWatcherRequest[]) { return true; } -function isEqualIgnore(i1: string[], i2: string[]) { - if (i1.length !== i2.length) { - return false; - } - for (let k = 0; k < i1.length; k++) { - if (i1[k] !== i2[k]) { - return false; - } - } - return true; +function isEqualIgnore(i1: readonly string[], i2: readonly string[]) { + return equals(i1, i2); } diff --git a/src/vs/workbench/api/browser/mainThreadEditor.ts b/src/vs/workbench/api/browser/mainThreadEditor.ts index 520801babe6..239f87096f1 100644 --- a/src/vs/workbench/api/browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/browser/mainThreadEditor.ts @@ -16,6 +16,7 @@ import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2 import { IApplyEditsOptions, IEditorPropertiesChangeData, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate, IUndoStopOptions, TextEditorRevealType } from 'vs/workbench/api/common/extHost.protocol'; import { IEditor } from 'vs/workbench/common/editor'; import { withNullAsUndefined } from 'vs/base/common/types'; +import { equals } from 'vs/base/common/arrays'; export interface IFocusTracker { onGainedFocus(): void; @@ -124,28 +125,12 @@ export class MainThreadTextEditorProperties { return null; } - private static _selectionsEqual(a: Selection[], b: Selection[]): boolean { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (!a[i].equalsSelection(b[i])) { - return false; - } - } - return true; + private static _selectionsEqual(a: readonly Selection[], b: readonly Selection[]): boolean { + return equals(a, b, (aValue, bValue) => aValue.equalsSelection(bValue)); } - private static _rangesEqual(a: Range[], b: Range[]): boolean { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (!a[i].equalsRange(b[i])) { - return false; - } - } - return true; + private static _rangesEqual(a: readonly Range[], b: readonly Range[]): boolean { + return equals(a, b, (aValue, bValue) => aValue.equalsRange(bValue)); } private static _optionsEqual(a: IResolvedTextEditorConfiguration, b: IResolvedTextEditorConfiguration): boolean { diff --git a/src/vs/workbench/api/common/extHostDocumentData.ts b/src/vs/workbench/api/common/extHostDocumentData.ts index b44527a2b51..3a166503923 100644 --- a/src/vs/workbench/api/common/extHostDocumentData.ts +++ b/src/vs/workbench/api/common/extHostDocumentData.ts @@ -12,6 +12,7 @@ import { ensureValidWordDefinition, getWordAtText } from 'vs/editor/common/model import { MainThreadDocumentsShape } from 'vs/workbench/api/common/extHost.protocol'; import { EndOfLine, Position, Range } from 'vs/workbench/api/common/extHostTypes'; import * as vscode from 'vscode'; +import { equals } from 'vs/base/common/arrays'; const _modeId2WordDefinition = new Map(); export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp | undefined): void { @@ -48,17 +49,8 @@ export class ExtHostDocumentData extends MirrorTextModel { this._isDirty = false; } - equalLines(lines: string[]): boolean { - const len = lines.length; - if (len !== this._lines.length) { - return false; - } - for (let i = 0; i < len; i++) { - if (lines[i] !== this._lines[i]) { - return false; - } - } - return true; + equalLines(lines: readonly string[]): boolean { + return equals(this._lines, lines); } get document(): vscode.TextDocument { diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 769d90c8d17..6bc3d01ff2c 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -10,7 +10,7 @@ import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { asPromise } from 'vs/base/common/async'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto } from './extHost.protocol'; -import { sortedDiff } from 'vs/base/common/arrays'; +import { sortedDiff, equals } from 'vs/base/common/arrays'; import { comparePaths } from 'vs/base/common/comparers'; import * as vscode from 'vscode'; import { ISplice } from 'vs/base/common/sequence'; @@ -126,18 +126,8 @@ function commandEquals(a: vscode.Command, b: vscode.Command): boolean { && (a.arguments && b.arguments ? compareArgs(a.arguments, b.arguments) : a.arguments === b.arguments); } -function commandListEquals(a: vscode.Command[], b: vscode.Command[]): boolean { - if (a.length !== b.length) { - return false; - } - - for (let i = 0; i < a.length; i++) { - if (!commandEquals(a[i], b[i])) { - return false; - } - } - - return true; +function commandListEquals(a: readonly vscode.Command[], b: readonly vscode.Command[]): boolean { + return equals(a, b, commandEquals); } export interface IValidateInput { diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts index dc77efc7ce5..006e90f2a76 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts @@ -29,6 +29,7 @@ import { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness, OverviewRule import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeybindingParser } from 'vs/base/common/keybindingParser'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { equals } from 'vs/base/common/arrays'; const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); const NLS_KB_LAYOUT_ERROR_MESSAGE = nls.localize('defineKeybinding.kbLayoutErrorMessage', "You won't be able to produce this key combination under your current keyboard layout."); @@ -265,18 +266,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { const aParts = KeybindingParser.parseUserBinding(a); const bParts = KeybindingParser.parseUserBinding(b); - - if (aParts.length !== bParts.length) { - return false; - } - - for (let i = 0, len = aParts.length; i < len; i++) { - if (!this._userBindingEquals(aParts[i], bParts[i])) { - return false; - } - } - - return true; + return equals(aParts, bParts, (a, b) => this._userBindingEquals(a, b)); } private static _userBindingEquals(a: SimpleKeybinding | ScanCodeBinding, b: SimpleKeybinding | ScanCodeBinding): boolean { From 30dc021bf728f7933dbd6d2fd5bc546917b6974b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 14:15:08 -0700 Subject: [PATCH 251/435] null -> undefined --- .../viewParts/overviewRuler/decorationsOverviewRuler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index a4e988745cb..9c1edf519e0 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -61,8 +61,8 @@ class Settings { const minimapOpts = options.get(EditorOption.minimap); const minimapEnabled = minimapOpts.enabled; const minimapSide = minimapOpts.side; - const backgroundColor = (minimapEnabled ? TokenizationRegistry.getDefaultBackground() : null); - if (backgroundColor === null || minimapSide === 'left') { + const backgroundColor = (minimapEnabled ? TokenizationRegistry.getDefaultBackground() : undefined); + if (typeof backgroundColor === 'undefined' || minimapSide === 'left') { this.backgroundColor = null; } else { this.backgroundColor = Color.Format.CSS.formatHex(backgroundColor); From 99dc069a0cfd633c2d5668c1b130efb4f124e675 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 14:16:01 -0700 Subject: [PATCH 252/435] Remove another duplicated array equals helper function --- src/vs/editor/common/config/commonEditorConfig.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 1ec61ff9751..f017f7e5fcf 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -304,18 +304,6 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed return EditorConfiguration2.computeOptions(this._validatedOptions, env); } - private static _primitiveArrayEquals(a: any[], b: any[]): boolean { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (a[i] !== b[i]) { - return false; - } - } - return true; - } - private static _subsetEquals(base: { [key: string]: any }, subset: { [key: string]: any }): boolean { for (const key in subset) { if (hasOwnProperty.call(subset, key)) { @@ -326,7 +314,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed continue; } if (Array.isArray(baseValue) && Array.isArray(subsetValue)) { - if (!this._primitiveArrayEquals(baseValue, subsetValue)) { + if (!arrays.equals(baseValue, subsetValue)) { return false; } continue; From d1b81e23db70c5c062c3adc162cb5f3477553176 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 7 Oct 2019 14:32:28 -0700 Subject: [PATCH 253/435] Remove applicationinsights-web dependency --- package.json | 3 +- remote/package.json | 1 - remote/web/package.json | 1 - remote/web/yarn.lock | 68 ------------------- remote/yarn.lock | 68 ------------------- .../code/browser/workbench/workbench-dev.html | 3 +- src/vs/code/browser/workbench/workbench.html | 4 +- .../common/abstractRemoteAgentService.ts | 21 ++++++ .../common/remoteAgentEnvironmentChannel.ts | 9 +++ .../remote/common/remoteAgentService.ts | 3 + .../telemetry/browser/telemetryService.ts | 47 +++---------- src/vs/workbench/workbench.web.api.ts | 13 +++- tslint.json | 3 +- yarn.lock | 68 ------------------- 14 files changed, 59 insertions(+), 253 deletions(-) diff --git a/package.json b/package.json index 72578602b1a..8d011529af5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "fd32ba99f225d591cb667f0bdf23dbb481743eab", + "distro": "4553fb95f2fbb4382c38983f9b29ea2076ed1865", "author": { "name": "Microsoft Corporation" }, @@ -28,7 +28,6 @@ "update-distro": "node build/npm/update-distro.js" }, "dependencies": { - "@microsoft/applicationinsights-web": "^2.1.1", "applicationinsights": "1.0.8", "chokidar": "3.1.0", "graceful-fs": "4.2.2", diff --git a/remote/package.json b/remote/package.json index 603799a71ea..d65eddd673d 100644 --- a/remote/package.json +++ b/remote/package.json @@ -2,7 +2,6 @@ "name": "vscode-reh", "version": "0.0.0", "dependencies": { - "@microsoft/applicationinsights-web": "^2.1.1", "applicationinsights": "1.0.8", "chokidar": "3.1.0", "cookie": "^0.4.0", diff --git a/remote/web/package.json b/remote/web/package.json index ab86c010ead..01e11a75fb2 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -2,7 +2,6 @@ "name": "vscode-web", "version": "0.0.0", "dependencies": { - "@microsoft/applicationinsights-web": "^2.1.1", "onigasm-umd": "^2.2.2", "semver-umd": "^5.5.3", "vscode-textmate": "^4.2.2", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index ccc09170f6f..696c1956a47 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -2,69 +2,6 @@ # yarn lockfile v1 -"@microsoft/applicationinsights-analytics-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.1.1.tgz#6d09c1915f808026e2d45165d04802f09affed59" - integrity sha512-VKIutoFKY99CyKwxLUuj6Vnq14/QwXo9/QSQDpYnHEjo+uKn7QmLsHqWw0K9uYNfNAXt4BZimX/zDg6jZtzeXg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-channel-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.1.1.tgz#e205eddd93e49d17d9e0711a612b4bfc9810888f" - integrity sha512-fYr9IAqtaEr9AmaPaL3SLQVT3t3GQzl+n74gpNKyAVakDIm0nYQ/bimjdcAhJMDf1VGNSPg/xICneyuZg7Wxlg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-common@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.1.1.tgz#27e6074584a7a3a8ca3f11f7ff2b7ff0f395bf2d" - integrity sha512-2hkS1Ia1FmAjCuYZ5JlG20/WgObqdsKtmK5YALAFGHIB4KSQ/Za1qazS+7GsG+E0F9UJivNWL1geUIcNqg5Qjg== - dependencies: - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-core-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.1.1.tgz#30fb6a519cc1c6119c419c4811ce72c260217d9e" - integrity sha512-4t4wf6SKqIcWEQDPg/uOhm+BxtHhu/AFreyEoYZmMfcxzAu33h1FtTQRtxBNbYH1+thiNZCh80yUpnT7d9Hrlw== - dependencies: - tslib "^1.9.3" - -"@microsoft/applicationinsights-dependencies-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.1.1.tgz#8154c3efcb24617d015d0bce7c2cc47797a8d3c4" - integrity sha512-yhb4EToBp+aI+qLo0h5NDNtoo3sDFV60uyIOK843YjzXqVotcXX/lRShlghTkJtYH09QhrdzDjViUHnD4sMFSQ== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-properties-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.1.1.tgz#ca34232766eb16167b5d87693e2ae5d94f2a1559" - integrity sha512-8l+/ppw6xKTam2RL4EHZ52Lcf217olw81j6kyBNKtIcGwSnLNHrFwEeF3vBWIteG2JKzlg1GhGjrkB3oxXsV2g== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-web@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web/-/applicationinsights-web-2.1.1.tgz#1a44eddda7c244b88d9eb052dab6c855682e4f05" - integrity sha512-crvhCkNsNxkFuPWmttyWNSAA96D5FxBtKS6UA9MV9f9XHevTfchf/E3AuU9JZcsXufWMQLwLrUQ9ZiA1QJ0EWA== - dependencies: - "@microsoft/applicationinsights-analytics-js" "2.1.1" - "@microsoft/applicationinsights-channel-js" "2.1.1" - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - "@microsoft/applicationinsights-dependencies-js" "2.1.1" - "@microsoft/applicationinsights-properties-js" "2.1.1" - nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -87,11 +24,6 @@ semver-umd@^5.5.3: resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e" integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw== -tslib@^1.9.3: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - vscode-textmate@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c" diff --git a/remote/yarn.lock b/remote/yarn.lock index 7538d4adfe0..a081e69b960 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -2,69 +2,6 @@ # yarn lockfile v1 -"@microsoft/applicationinsights-analytics-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.1.1.tgz#6d09c1915f808026e2d45165d04802f09affed59" - integrity sha512-VKIutoFKY99CyKwxLUuj6Vnq14/QwXo9/QSQDpYnHEjo+uKn7QmLsHqWw0K9uYNfNAXt4BZimX/zDg6jZtzeXg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-channel-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.1.1.tgz#e205eddd93e49d17d9e0711a612b4bfc9810888f" - integrity sha512-fYr9IAqtaEr9AmaPaL3SLQVT3t3GQzl+n74gpNKyAVakDIm0nYQ/bimjdcAhJMDf1VGNSPg/xICneyuZg7Wxlg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-common@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.1.1.tgz#27e6074584a7a3a8ca3f11f7ff2b7ff0f395bf2d" - integrity sha512-2hkS1Ia1FmAjCuYZ5JlG20/WgObqdsKtmK5YALAFGHIB4KSQ/Za1qazS+7GsG+E0F9UJivNWL1geUIcNqg5Qjg== - dependencies: - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-core-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.1.1.tgz#30fb6a519cc1c6119c419c4811ce72c260217d9e" - integrity sha512-4t4wf6SKqIcWEQDPg/uOhm+BxtHhu/AFreyEoYZmMfcxzAu33h1FtTQRtxBNbYH1+thiNZCh80yUpnT7d9Hrlw== - dependencies: - tslib "^1.9.3" - -"@microsoft/applicationinsights-dependencies-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.1.1.tgz#8154c3efcb24617d015d0bce7c2cc47797a8d3c4" - integrity sha512-yhb4EToBp+aI+qLo0h5NDNtoo3sDFV60uyIOK843YjzXqVotcXX/lRShlghTkJtYH09QhrdzDjViUHnD4sMFSQ== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-properties-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.1.1.tgz#ca34232766eb16167b5d87693e2ae5d94f2a1559" - integrity sha512-8l+/ppw6xKTam2RL4EHZ52Lcf217olw81j6kyBNKtIcGwSnLNHrFwEeF3vBWIteG2JKzlg1GhGjrkB3oxXsV2g== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-web@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web/-/applicationinsights-web-2.1.1.tgz#1a44eddda7c244b88d9eb052dab6c855682e4f05" - integrity sha512-crvhCkNsNxkFuPWmttyWNSAA96D5FxBtKS6UA9MV9f9XHevTfchf/E3AuU9JZcsXufWMQLwLrUQ9ZiA1QJ0EWA== - dependencies: - "@microsoft/applicationinsights-analytics-js" "2.1.1" - "@microsoft/applicationinsights-channel-js" "2.1.1" - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - "@microsoft/applicationinsights-dependencies-js" "2.1.1" - "@microsoft/applicationinsights-properties-js" "2.1.1" - agent-base@4, agent-base@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" @@ -435,11 +372,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tslib@^1.9.3: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 910666edf08..b59b7a2b49b 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -14,7 +14,7 @@ default-src 'self'; img-src 'self' https: data: blob:; media-src 'none'; - script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-AMRGFXNZ7mBnD/6F4lTV00XAjE5CBSM7ZeIv3DIp5YM=' 'sha256-meDZW3XhN5JmdjFUrWGhTouRKBiWYtXHltaKnqn/WMo='; + script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-/Ua2yZoIzhImbjP5mnPF6fXTgzsTEtN8hPP1XAB1n6U=' 'sha256-meDZW3XhN5JmdjFUrWGhTouRKBiWYtXHltaKnqn/WMo='; child-src 'self'; frame-src 'self' https://*.vscode-webview-test.com; worker-src 'self'; @@ -50,7 +50,6 @@ 'xterm-addon-search': `${window.location.origin}/static/remote/web/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, 'xterm-addon-web-links': `${window.location.origin}/static/remote/web/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, 'semver-umd': `${window.location.origin}/static/remote/web/node_modules/semver-umd/lib/semver-umd.js`, - '@microsoft/applicationinsights-web': `${window.location.origin}/static/remote/web/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`, } }; diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index 97d78ce7f9e..f3caa5350bf 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -14,7 +14,7 @@ default-src 'self'; img-src 'self' https: data: blob:; media-src 'none'; - script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-4DqvCTjCHj2KW4QxC/Yt6uBwMRyYiEg7kOoykSEkonQ='; + script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-lrlqPnPED1SjcFocGzCtf6ikbQdTUwJKs8VprSqhvS4='; child-src 'self'; frame-src 'self' https://*.vscode-webview-test.com; worker-src 'self'; @@ -37,7 +37,6 @@ - @@ -55,7 +54,6 @@ 'xterm-addon-search': `${window.location.origin}/static/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, 'xterm-addon-web-links': `${window.location.origin}/static/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, 'semver-umd': `${window.location.origin}/static/node_modules/semver-umd/lib/semver-umd.js`, - '@microsoft/applicationinsights-web': `${window.location.origin}/static/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`, } }; diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index c889524ee61..93008e7624b 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -21,6 +21,7 @@ import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics import { Emitter } from 'vs/base/common/event'; import { ISignService } from 'vs/platform/sign/common/sign'; import { ILogService } from 'vs/platform/log/common/log'; +import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; export abstract class AbstractRemoteAgentService extends Disposable { @@ -69,6 +70,26 @@ export abstract class AbstractRemoteAgentService extends Disposable { return Promise.resolve(undefined); } + + logTelemetry(eventName: string, data: ITelemetryData): Promise { + const connection = this.getConnection(); + if (connection) { + const client = new RemoteExtensionEnvironmentChannelClient(connection.getChannel('remoteextensionsenvironment')); + return client.logTelemetry(eventName, data); + } + + return Promise.resolve(undefined); + } + + flushTelemetry(): Promise { + const connection = this.getConnection(); + if (connection) { + const client = new RemoteExtensionEnvironmentChannelClient(connection.getChannel('remoteextensionsenvironment')); + return client.flushTelemetry(); + } + + return Promise.resolve(undefined); + } } export class RemoteAgentConnection extends Disposable implements IRemoteAgentConnection { diff --git a/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts b/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts index a1877e037aa..93a0c25a574 100644 --- a/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts +++ b/src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts @@ -10,6 +10,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics'; import { RemoteAuthorities } from 'vs/base/common/network'; +import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; export interface IGetEnvironmentDataArguments { language: string; @@ -70,4 +71,12 @@ export class RemoteExtensionEnvironmentChannelClient { disableTelemetry(): Promise { return this.channel.call('disableTelemetry'); } + + logTelemetry(eventName: string, data: ITelemetryData): Promise { + return this.channel.call('logTelemetry', { eventName, data }); + } + + flushTelemetry(): Promise { + return this.channel.call('flushTelemetry'); + } } diff --git a/src/vs/workbench/services/remote/common/remoteAgentService.ts b/src/vs/workbench/services/remote/common/remoteAgentService.ts index 1cda189b53e..9200f1be530 100644 --- a/src/vs/workbench/services/remote/common/remoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/remoteAgentService.ts @@ -9,6 +9,7 @@ import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics'; import { Event } from 'vs/base/common/event'; import { PersistenConnectionEvent as PersistentConnectionEvent, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection'; +import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; export const RemoteExtensionLogFileName = 'remoteagent'; @@ -23,6 +24,8 @@ export interface IRemoteAgentService { getEnvironment(bail?: boolean): Promise; getDiagnosticInfo(options: IDiagnosticInfoOptions): Promise; disableTelemetry(): Promise; + logTelemetry(eventName: string, data?: ITelemetryData): Promise; + flushTelemetry(): Promise; } export interface IRemoteAgentConnection { diff --git a/src/vs/workbench/services/telemetry/browser/telemetryService.ts b/src/vs/workbench/services/telemetry/browser/telemetryService.ts index b06ed3920cb..aaea9e997d8 100644 --- a/src/vs/workbench/services/telemetry/browser/telemetryService.ts +++ b/src/vs/workbench/services/telemetry/browser/telemetryService.ts @@ -15,52 +15,24 @@ import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/pla import { IStorageService } from 'vs/platform/storage/common/storage'; import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/browser/workbenchCommonProperties'; import { IProductService } from 'vs/platform/product/common/productService'; -import { ApplicationInsights } from '@microsoft/applicationinsights-web'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; export class WebTelemetryAppender implements ITelemetryAppender { - private _aiClient?: ApplicationInsights; - constructor(aiKey: string, private _logService: ILogService) { - const initConfig = { - config: { - instrumentationKey: aiKey, - endpointUrl: 'https://vortex.data.microsoft.com/collect/v1', - emitLineDelimitedJson: true, - autoTrackPageVisitTime: false, - disableExceptionTracking: true, - disableAjaxTracking: true - } - }; - - this._aiClient = new ApplicationInsights(initConfig); - this._aiClient.loadAppInsights(); - } + constructor(private _logService: ILogService, private _appender: ITelemetryAppender) { } log(eventName: string, data: any): void { - if (!this._aiClient) { - return; - } - data = validateTelemetryData(data); this._logService.trace(`telemetry/${eventName}`, data); - this._aiClient.trackEvent({ - name: 'monacoworkbench/' + eventName, + this._appender.log('/monacoworkbench/' + eventName, { properties: data.properties, measurements: data.measurements }); } flush(): Promise { - if (this._aiClient) { - return new Promise(resolve => { - this._aiClient!.flush(); - this._aiClient = undefined; - resolve(undefined); - }); - } - - return Promise.resolve(); + return this._appender.flush(); } } @@ -75,15 +47,16 @@ export class TelemetryService extends Disposable implements ITelemetryService { @ILogService logService: ILogService, @IConfigurationService configurationService: IConfigurationService, @IStorageService storageService: IStorageService, - @IProductService productService: IProductService + @IProductService productService: IProductService, + @IRemoteAgentService remoteAgentService: IRemoteAgentService ) { super(); - const aiKey = productService.aiConfig && productService.aiConfig.asimovKey; - if (!environmentService.isExtensionDevelopment && !environmentService.args['disable-telemetry'] && !!productService.enableTelemetry && !!aiKey) { + if (!environmentService.args['disable-telemetry'] && !!productService.enableTelemetry) { + const telemetryProvider = environmentService.options && environmentService.options.telemetryAppender || { log: remoteAgentService.logTelemetry, flush: remoteAgentService.flushTelemetry }; const config: ITelemetryServiceConfig = { - appender: combinedAppender(new WebTelemetryAppender(aiKey, logService), new LogAppender(logService)), - commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), + appender: combinedAppender(new WebTelemetryAppender(logService, telemetryProvider), new LogAppender(logService)), + commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority), piiPaths: [environmentService.appRoot] }; diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index 4833155c493..3c30b2fd899 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -15,6 +15,7 @@ import { LogLevel } from 'vs/platform/log/common/log'; import { IUpdateProvider, IUpdate } from 'vs/workbench/services/update/browser/updateService'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils'; import { IWorkspaceProvider, IWorkspace } from 'vs/workbench/services/host/browser/browserHostService'; interface IWorkbenchConstructionOptions { @@ -82,11 +83,18 @@ interface IWorkbenchConstructionOptions { */ logLevel?: LogLevel; + /** * Experimental: Support for update reporting. */ updateProvider?: IUpdateProvider; + /** + * Experimental: If provided, will be called when logging telemetry events. + */ + telemetryAppender?: ITelemetryAppender; + + /** * Experimental: Support adding additional properties to telemetry. */ @@ -150,5 +158,8 @@ export { // Updates IUpdateProvider, - IUpdate + IUpdate, + + // Telemetry + ITelemetryAppender }; diff --git a/tslint.json b/tslint.json index 31adda1904b..a0feadaf2c0 100644 --- a/tslint.json +++ b/tslint.json @@ -472,8 +472,7 @@ "**/vs/workbench/api/{common,browser}/**", "**/vs/workbench/services/**/{common,browser}/**", "vscode-textmate", - "onigasm-umd", - "@microsoft/applicationinsights-web" + "onigasm-umd" ] }, { diff --git a/yarn.lock b/yarn.lock index 2e1a8d76c61..9c27370a796 100644 --- a/yarn.lock +++ b/yarn.lock @@ -95,69 +95,6 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@microsoft/applicationinsights-analytics-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.1.1.tgz#6d09c1915f808026e2d45165d04802f09affed59" - integrity sha512-VKIutoFKY99CyKwxLUuj6Vnq14/QwXo9/QSQDpYnHEjo+uKn7QmLsHqWw0K9uYNfNAXt4BZimX/zDg6jZtzeXg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-channel-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.1.1.tgz#e205eddd93e49d17d9e0711a612b4bfc9810888f" - integrity sha512-fYr9IAqtaEr9AmaPaL3SLQVT3t3GQzl+n74gpNKyAVakDIm0nYQ/bimjdcAhJMDf1VGNSPg/xICneyuZg7Wxlg== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-common@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.1.1.tgz#27e6074584a7a3a8ca3f11f7ff2b7ff0f395bf2d" - integrity sha512-2hkS1Ia1FmAjCuYZ5JlG20/WgObqdsKtmK5YALAFGHIB4KSQ/Za1qazS+7GsG+E0F9UJivNWL1geUIcNqg5Qjg== - dependencies: - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-core-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.1.1.tgz#30fb6a519cc1c6119c419c4811ce72c260217d9e" - integrity sha512-4t4wf6SKqIcWEQDPg/uOhm+BxtHhu/AFreyEoYZmMfcxzAu33h1FtTQRtxBNbYH1+thiNZCh80yUpnT7d9Hrlw== - dependencies: - tslib "^1.9.3" - -"@microsoft/applicationinsights-dependencies-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.1.1.tgz#8154c3efcb24617d015d0bce7c2cc47797a8d3c4" - integrity sha512-yhb4EToBp+aI+qLo0h5NDNtoo3sDFV60uyIOK843YjzXqVotcXX/lRShlghTkJtYH09QhrdzDjViUHnD4sMFSQ== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-properties-js@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.1.1.tgz#ca34232766eb16167b5d87693e2ae5d94f2a1559" - integrity sha512-8l+/ppw6xKTam2RL4EHZ52Lcf217olw81j6kyBNKtIcGwSnLNHrFwEeF3vBWIteG2JKzlg1GhGjrkB3oxXsV2g== - dependencies: - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - tslib "^1.9.3" - -"@microsoft/applicationinsights-web@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web/-/applicationinsights-web-2.1.1.tgz#1a44eddda7c244b88d9eb052dab6c855682e4f05" - integrity sha512-crvhCkNsNxkFuPWmttyWNSAA96D5FxBtKS6UA9MV9f9XHevTfchf/E3AuU9JZcsXufWMQLwLrUQ9ZiA1QJ0EWA== - dependencies: - "@microsoft/applicationinsights-analytics-js" "2.1.1" - "@microsoft/applicationinsights-channel-js" "2.1.1" - "@microsoft/applicationinsights-common" "2.1.1" - "@microsoft/applicationinsights-core-js" "2.1.1" - "@microsoft/applicationinsights-dependencies-js" "2.1.1" - "@microsoft/applicationinsights-properties-js" "2.1.1" - "@types/commander@^2.11.0": version "2.12.2" resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae" @@ -8457,11 +8394,6 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslib@^1.9.3: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - tslint@^5.16.0: version "5.16.0" resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.16.0.tgz#ae61f9c5a98d295b9a4f4553b1b1e831c1984d67" From 4e2caaa6464a959aa7be149c95d908fd055ee765 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 14:35:04 -0700 Subject: [PATCH 254/435] Use array.find in more places of re-implementing it with for loops --- src/vs/editor/contrib/gotoError/gotoError.ts | 9 ++------ .../modes/supports/characterPair.test.ts | 10 +++------ .../files/test/node/diskFileService.test.ts | 14 ++++--------- src/vs/workbench/browser/editor.ts | 9 ++------ .../browser/parts/editor/editorDropTarget.ts | 9 ++------ .../browser/parts/statusbar/statusbarPart.ts | 10 ++------- src/vs/workbench/common/notifications.ts | 21 +++---------------- .../output/common/outputLinkComputer.ts | 11 +++------- .../browser/preferencesRenderers.ts | 8 ++----- .../tasks/browser/abstractTaskService.ts | 8 ++----- .../terminal/browser/terminalService.ts | 10 +++------ .../credentials/browser/credentialsService.ts | 18 +++++++--------- .../themes/browser/fileIconThemeStore.ts | 17 ++++----------- .../workbench/test/workbenchTestServices.ts | 11 +++------- 14 files changed, 42 insertions(+), 123 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index c552b5f4406..291b30cbb25 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -20,7 +20,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { MarkerNavigationWidget } from './gotoErrorWidget'; import { compare } from 'vs/base/common/strings'; -import { binarySearch } from 'vs/base/common/arrays'; +import { binarySearch, find } from 'vs/base/common/arrays'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { onUnexpectedError } from 'vs/base/common/errors'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; @@ -173,12 +173,7 @@ class MarkerModel { } public findMarkerAtPosition(pos: Position): IMarker | undefined { - for (const marker of this._markers) { - if (Range.containsPosition(marker, pos)) { - return marker; - } - } - return undefined; + return find(this._markers, marker => Range.containsPosition(marker, pos)); } public get total() { diff --git a/src/vs/editor/test/common/modes/supports/characterPair.test.ts b/src/vs/editor/test/common/modes/supports/characterPair.test.ts index 3f3f6880450..ed059c8a0cb 100644 --- a/src/vs/editor/test/common/modes/supports/characterPair.test.ts +++ b/src/vs/editor/test/common/modes/supports/characterPair.test.ts @@ -8,6 +8,7 @@ import { StandardTokenType } from 'vs/editor/common/modes'; import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair'; import { TokenText, createFakeScopedLineTokens } from 'vs/editor/test/common/modesTestUtils'; import { StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration'; +import { find } from 'vs/base/common/arrays'; suite('CharacterPairSupport', () => { @@ -53,13 +54,8 @@ suite('CharacterPairSupport', () => { assert.deepEqual(characaterPairSupport.getSurroundingPairs(), []); }); - function findAutoClosingPair(characterPairSupport: CharacterPairSupport, character: string): StandardAutoClosingPairConditional | null { - for (const autoClosingPair of characterPairSupport.getAutoClosingPairs()) { - if (autoClosingPair.open === character) { - return autoClosingPair; - } - } - return null; + function findAutoClosingPair(characterPairSupport: CharacterPairSupport, character: string): StandardAutoClosingPairConditional | undefined { + return find(characterPairSupport.getAutoClosingPairs(), autoClosingPair => autoClosingPair.open === character); } function testShouldAutoClose(characterPairSupport: CharacterPairSupport, line: TokenText[], character: string, column: number): boolean { diff --git a/src/vs/platform/files/test/node/diskFileService.test.ts b/src/vs/platform/files/test/node/diskFileService.test.ts index 3f5c57ec1a8..5c69ce8fdcb 100644 --- a/src/vs/platform/files/test/node/diskFileService.test.ts +++ b/src/vs/platform/files/test/node/diskFileService.test.ts @@ -21,19 +21,13 @@ import { isLinux, isWindows } from 'vs/base/common/platform'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { isEqual } from 'vs/base/common/resources'; import { VSBuffer, VSBufferReadable, toVSBufferReadableStream, VSBufferReadableStream, bufferToReadable, bufferToStream } from 'vs/base/common/buffer'; +import { find } from 'vs/base/common/arrays'; -function getByName(root: IFileStat, name: string): IFileStat | null { +function getByName(root: IFileStat, name: string): IFileStat | undefined { if (root.children === undefined) { - return null; + return undefined; } - - for (const child of root.children) { - if (child.name === name) { - return child; - } - } - - return null; + return find(root.children, child => child.name === name); } function toLineByLineReadable(content: string): VSBufferReadable { diff --git a/src/vs/workbench/browser/editor.ts b/src/vs/workbench/browser/editor.ts index a8b4de85142..d441fb2f0d9 100644 --- a/src/vs/workbench/browser/editor.ts +++ b/src/vs/workbench/browser/editor.ts @@ -8,6 +8,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { Registry } from 'vs/platform/registry/common/platform'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { find } from 'vs/base/common/arrays'; export interface IEditorDescriptor { instantiate(instantiationService: IInstantiationService): BaseEditor; @@ -140,13 +141,7 @@ class EditorRegistry implements IEditorRegistry { } getEditorById(editorId: string): EditorDescriptor | undefined { - for (const editor of this.editors) { - if (editor.getId() === editorId) { - return editor; - } - } - - return undefined; + return find(this.editors, editor => editor.getId() === editorId); } getEditors(): readonly EditorDescriptor[] { diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index da2fa254db3..3a11f85bbaf 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -16,6 +16,7 @@ import { GroupDirection, MergeGroupMode } from 'vs/workbench/services/editor/com import { toDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { find } from 'vs/base/common/arrays'; interface IDropOperation { splitDirection?: GroupDirection; @@ -544,13 +545,7 @@ export class EditorDropTarget extends Themable { private findTargetGroupView(child: HTMLElement): IEditorGroupView | undefined { const groups = this.accessor.groups; - for (const groupView of groups) { - if (isAncestor(child, groupView.element)) { - return groupView; - } - } - - return undefined; + return find(groups, groupView => isAncestor(child, groupView.element)); } private updateContainer(isDraggedOver: boolean): void { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 5d73c777540..418c8b2a56f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -27,7 +27,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { coalesce } from 'vs/base/common/arrays'; +import { coalesce, find } from 'vs/base/common/arrays'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -176,13 +176,7 @@ class StatusbarViewModel extends Disposable { } findEntry(container: HTMLElement): IStatusbarViewModelEntry | undefined { - for (const entry of this._entries) { - if (entry.container === container) { - return entry; - } - } - - return undefined; + return find(this._entries, entry => entry.container === container); } getEntries(alignment: StatusbarAlignment): IStatusbarViewModelEntry[] { diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index 9546898f8c9..6b0e55ec327 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -12,6 +12,7 @@ import { Action } from 'vs/base/common/actions'; import { isErrorWithActions } from 'vs/base/common/errorsWithActions'; import { startsWith } from 'vs/base/common/strings'; import { localize } from 'vs/nls'; +import { find, equals } from 'vs/base/common/arrays'; export interface INotificationsModel { @@ -169,13 +170,7 @@ export class NotificationsModel extends Disposable implements INotificationsMode } private findNotification(item: INotificationViewItem): INotificationViewItem | undefined { - for (const notification of this._notifications) { - if (notification.equals(item)) { - return notification; - } - } - - return undefined; + return find(this._notifications, notification => notification.equals(item)); } private createViewItem(notification: INotification): INotificationViewItem | null { @@ -641,17 +636,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie const primaryActions = (this._actions && this._actions.primary) || []; const otherPrimaryActions = (other.actions && other.actions.primary) || []; - if (primaryActions.length !== otherPrimaryActions.length) { - return false; - } - - for (let i = 0; i < primaryActions.length; i++) { - if ((primaryActions[i].id + primaryActions[i].label) !== (otherPrimaryActions[i].id + otherPrimaryActions[i].label)) { - return false; - } - } - - return true; + return equals(primaryActions, otherPrimaryActions, (a, b) => (a.id + a.label) === (b.id + b.label)); } } diff --git a/src/vs/workbench/contrib/output/common/outputLinkComputer.ts b/src/vs/workbench/contrib/output/common/outputLinkComputer.ts index ee681d2dccf..b61cccb5e95 100644 --- a/src/vs/workbench/contrib/output/common/outputLinkComputer.ts +++ b/src/vs/workbench/contrib/output/common/outputLinkComputer.ts @@ -12,6 +12,7 @@ import * as strings from 'vs/base/common/strings'; import { Range } from 'vs/editor/common/core/range'; import { isWindows } from 'vs/base/common/platform'; import { Schemas } from 'vs/base/common/network'; +import { find } from 'vs/base/common/arrays'; export interface ICreateData { workspaceFolders: string[]; @@ -44,15 +45,9 @@ export class OutputLinkComputer { }); } - private getModel(uri: string): IMirrorModel | null { + private getModel(uri: string): IMirrorModel | undefined { const models = this.ctx.getMirrorModels(); - for (const model of models) { - if (model.uri.toString() === uri) { - return model; - } - } - - return null; + return find(models, model => model.uri.toString() === uri); } public computeLinks(uri: string): Promise { diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts index 2881d09fec2..2b8d5a82f17 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts @@ -32,6 +32,7 @@ import { DefaultSettingsEditorModel, SettingsEditorModel, WorkspaceConfiguration import { IMarkerService, IMarkerData, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { find } from 'vs/base/common/arrays'; export interface IPreferencesRenderer extends IDisposable { readonly preferencesModel: IPreferencesEditorModel; @@ -321,12 +322,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR const { key, overrideOf } = setting; if (overrideOf) { const setting = this.getSetting(overrideOf); - for (const override of setting!.overrides!) { - if (override.key === key) { - return override; - } - } - return undefined; + return find(setting!.overrides!, override => override.key === key); } const settingsGroups = this.filterResult ? this.filterResult.filteredGroups : this.preferencesModel.settingsGroups; return this.getPreference(key, settingsGroups); diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 6a3efa5fd4b..ec2a34ea079 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -77,6 +77,7 @@ import { applyEdits } from 'vs/base/common/jsonEdit'; import { ITextEditor } from 'vs/workbench/common/editor'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { find } from 'vs/base/common/arrays'; export namespace ConfigureTaskAction { export const ID = 'workbench.action.tasks.configureTaskRunner'; @@ -515,12 +516,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (!values) { return undefined; } - for (const task of values) { - if (task.matches(key, compareId)) { - return task; - } - } - return undefined; + return find(values, task => task.matches(key, compareId)); }); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index a0772f91fd5..6bb7530ed79 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -29,6 +29,7 @@ import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/termi import { isWindows, isMacintosh, OperatingSystem } from 'vs/base/common/platform'; import { basename } from 'vs/base/common/path'; import { IOpenFileRequest } from 'vs/platform/windows/common/windows'; +import { find } from 'vs/base/common/arrays'; interface IExtHostReadyEntry { promise: Promise; @@ -414,13 +415,8 @@ export class TerminalService implements ITerminalService { instance.addDisposable(instance.onFocus(this._onActiveInstanceChanged.fire, this._onActiveInstanceChanged)); } - private _getTabForInstance(instance: ITerminalInstance): ITerminalTab | null { - for (const tab of this._terminalTabs) { - if (tab.terminalInstances.indexOf(instance) !== -1) { - return tab; - } - } - return null; + private _getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined { + return find(this._terminalTabs, tab => tab.terminalInstances.indexOf(instance) !== -1); } public showPanel(focus?: boolean): Promise { diff --git a/src/vs/workbench/services/credentials/browser/credentialsService.ts b/src/vs/workbench/services/credentials/browser/credentialsService.ts index 20946f64ae1..d50c058d3aa 100644 --- a/src/vs/workbench/services/credentials/browser/credentialsService.ts +++ b/src/vs/workbench/services/credentials/browser/credentialsService.ts @@ -6,6 +6,7 @@ import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { find } from 'vs/base/common/arrays'; export interface ICredentialsProvider { getPassword(service: string, account: string): Promise; @@ -14,7 +15,7 @@ export interface ICredentialsProvider { deletePassword(service: string, account: string): Promise; findPassword(service: string): Promise; - findCredentials(service: string): Promise>; + findCredentials(service: string): Promise>; } export class BrowserCredentialsService implements ICredentialsService { @@ -47,7 +48,7 @@ export class BrowserCredentialsService implements ICredentialsService { return this.credentialsProvider.findPassword(service); } - findCredentials(service: string): Promise> { + findCredentials(service: string): Promise> { return this.credentialsProvider.findCredentials(service); } } @@ -88,17 +89,12 @@ class InMemoryCredentialsProvider implements ICredentialsProvider { return credential ? credential.password : null; } - private doFindPassword(service: string, account?: string): ICredential | null { - for (const credential of this.credentials) { - if (credential.service === service && (typeof account !== 'string' || credential.account === account)) { - return credential; - } - } - - return null; + private doFindPassword(service: string, account?: string): ICredential | undefined { + return find(this.credentials, credential => + credential.service === service && (typeof account !== 'string' || credential.account === account)); } - async findCredentials(service: string): Promise> { + async findCredentials(service: string): Promise> { return this.credentials .filter(credential => credential.service === service) .map(({ account, password }) => ({ account, password })); diff --git a/src/vs/workbench/services/themes/browser/fileIconThemeStore.ts b/src/vs/workbench/services/themes/browser/fileIconThemeStore.ts index e4eb557f54c..0afad15ee6c 100644 --- a/src/vs/workbench/services/themes/browser/fileIconThemeStore.ts +++ b/src/vs/workbench/services/themes/browser/fileIconThemeStore.ts @@ -14,6 +14,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { FileIconThemeData } from 'vs/workbench/services/themes/browser/fileIconThemeData'; import { URI } from 'vs/base/common/uri'; import { Disposable } from 'vs/base/common/lifecycle'; +import { find } from 'vs/base/common/arrays'; const iconThemeExtPoint = ExtensionsRegistry.registerExtensionPoint({ extensionPoint: 'iconThemes', @@ -62,7 +63,7 @@ export class FileIconThemeStore extends Disposable { private initialize() { iconThemeExtPoint.setHandler((extensions) => { - const previousIds: { [key: string]: boolean } = {}; + const previousIds: { [key: string]: boolean; } = {}; const added: FileIconThemeData[] = []; for (const theme of this.knownIconThemes) { previousIds[theme.id] = true; @@ -131,12 +132,7 @@ export class FileIconThemeStore extends Disposable { return Promise.resolve(FileIconThemeData.noIconTheme()); } return this.getFileIconThemes().then(allIconSets => { - for (let iconSet of allIconSets) { - if (iconSet.id === iconTheme) { - return iconSet; - } - } - return undefined; + return find(allIconSets, iconSet => iconSet.id === iconTheme); }); } @@ -145,12 +141,7 @@ export class FileIconThemeStore extends Disposable { return Promise.resolve(FileIconThemeData.noIconTheme()); } return this.getFileIconThemes().then(allIconSets => { - for (let iconSet of allIconSets) { - if (iconSet.settingsId === settingsId) { - return iconSet; - } - } - return undefined; + return find(allIconSets, iconSet => iconSet.settingsId === settingsId); }); } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index f85d68fb3b7..3d1186ff31a 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -91,6 +91,7 @@ import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, import { IBackupMainService, IWorkspaceBackupInfo } from 'vs/platform/backup/electron-main/backup'; import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { find } from 'vs/base/common/arrays'; export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined); @@ -700,14 +701,8 @@ export class TestEditorGroupsService implements IEditorGroupsService { return this.groups; } - getGroup(identifier: number): IEditorGroup { - for (const group of this.groups) { - if (group.id === identifier) { - return group; - } - } - - return undefined!; + getGroup(identifier: number): IEditorGroup | undefined { + return find(this.groups, group => group.id === identifier); } getLabel(_identifier: number): string { From 2719c1ddc06c737b0aa0010d47687a4088395101 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 14:43:08 -0700 Subject: [PATCH 255/435] Replacing more for loops with .every/.some or arrays.equals --- src/vs/base/node/macAddress.ts | 16 ++++------- src/vs/editor/common/controller/cursor.ts | 27 ++++--------------- .../common/monarch/monarchCompile.ts | 13 +-------- .../common/configurationModels.ts | 8 +----- .../contextkey/browser/contextKeyService.ts | 14 ++-------- .../watcher/unix/chokidarWatcherService.ts | 12 ++------- .../telemetry/node/commonProperties.ts | 10 ++----- .../platform/workspaces/common/workspaces.ts | 7 +---- .../api/browser/mainThreadSaveParticipant.ts | 20 +++++++------- src/vs/workbench/api/common/extHostTypes.ts | 7 +---- .../preferences/browser/settingsTreeModels.ts | 10 ++----- 11 files changed, 31 insertions(+), 113 deletions(-) diff --git a/src/vs/base/node/macAddress.ts b/src/vs/base/node/macAddress.ts index dd36be22344..524b136c06b 100644 --- a/src/vs/base/node/macAddress.ts +++ b/src/vs/base/node/macAddress.ts @@ -11,21 +11,15 @@ const cmdline = { unix: '/sbin/ifconfig -a || /sbin/ip link' }; -const invalidMacAddresses = [ +const invalidMacAddresses = new Set([ '00:00:00:00:00:00', 'ff:ff:ff:ff:ff:ff', 'ac:de:48:00:11:22' -]; +]); function validateMacAddress(candidate: string): boolean { - let tempCandidate = candidate.replace(/\-/g, ':').toLowerCase(); - for (let invalidMacAddress of invalidMacAddresses) { - if (invalidMacAddress === tempCandidate) { - return false; - } - } - - return true; + const tempCandidate = candidate.replace(/\-/g, ':').toLowerCase(); + return !invalidMacAddresses.has(tempCandidate); } export function getMac(): Promise { @@ -66,4 +60,4 @@ function doGetMac(): Promise { reject(err); } }); -} \ No newline at end of file +} diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 4213345fc97..4b4fb9cc473 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -21,14 +21,10 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { dispose } from 'vs/base/common/lifecycle'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { equals } from 'vs/base/common/arrays'; -function containsLineMappingChanged(events: viewEvents.ViewEvent[]): boolean { - for (let i = 0, len = events.length; i < len; i++) { - if (events[i].type === viewEvents.ViewEventType.ViewLineMappingChanged) { - return true; - } - } - return false; +function containsLineMappingChanged(events: readonly viewEvents.ViewEvent[]): boolean { + return events.some(event => event.type === viewEvents.ViewEventType.ViewLineMappingChanged); } export class CursorStateChangedEvent { @@ -73,15 +69,7 @@ export class CursorModelState { if (this.modelVersionId !== other.modelVersionId) { return false; } - if (this.cursorState.length !== other.cursorState.length) { - return false; - } - for (let i = 0, len = this.cursorState.length; i < len; i++) { - if (!this.cursorState[i].equals(other.cursorState[i])) { - return false; - } - } - return true; + return equals(this.cursorState, other.cursorState, (a, b) => a.equals(b)); } } @@ -949,12 +937,7 @@ class CommandExecutor { } private static _arrayIsEmpty(commands: (editorCommon.ICommand | null)[]): boolean { - for (let i = 0, len = commands.length; i < len; i++) { - if (commands[i]) { - return false; - } - } - return true; + return commands.every(command => !command); } private static _getEditOperations(ctx: IExecContext, commands: (editorCommon.ICommand | null)[]): ICommandsData { diff --git a/src/vs/editor/standalone/common/monarch/monarchCompile.ts b/src/vs/editor/standalone/common/monarch/monarchCompile.ts index 2c98c6ba429..62f0d4313c6 100644 --- a/src/vs/editor/standalone/common/monarch/monarchCompile.ts +++ b/src/vs/editor/standalone/common/monarch/monarchCompile.ts @@ -21,18 +21,7 @@ import { IMonarchLanguage, IMonarchLanguageBracket } from 'vs/editor/standalone/ */ function isArrayOf(elemType: (x: any) => boolean, obj: any): boolean { - if (!obj) { - return false; - } - if (!(Array.isArray(obj))) { - return false; - } - for (const el of obj) { - if (!(elemType(el))) { - return false; - } - } - return true; + return Array.isArray(obj) && obj.every(elemType); } function bool(prop: any, defValue: boolean): boolean { diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 7750ef0b32d..452e41724c4 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -663,13 +663,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i configurationModelsToSearch.push(...this._changedConfigurationByResource.values()); } - for (const configuration of configurationModelsToSearch) { - if (this.doesConfigurationContains(configuration, config)) { - return true; - } - } - - return false; + return configurationModelsToSearch.some(configuration => this.doesConfigurationContains(configuration, config)); } private changeWithKeys(keys: string[], resource?: URI): void { diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 8efe90bd137..d11c36e17ae 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -203,24 +203,14 @@ class SimpleContextKeyChangeEvent implements IContextKeyChangeEvent { class ArrayContextKeyChangeEvent implements IContextKeyChangeEvent { constructor(readonly keys: string[]) { } affectsSome(keys: IReadableSet): boolean { - for (const key of this.keys) { - if (keys.has(key)) { - return true; - } - } - return false; + return this.keys.some(key => keys.has(key)); } } class CompositeContextKeyChangeEvent implements IContextKeyChangeEvent { constructor(readonly events: IContextKeyChangeEvent[]) { } affectsSome(keys: IReadableSet): boolean { - for (const e of this.events) { - if (e.affectsSome(keys)) { - return true; - } - } - return false; + return this.events.some(e => e.affectsSome(keys)); } } diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index bd4632e1915..3fff232b834 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -352,16 +352,8 @@ export function normalizeRoots(requests: IWatcherRequest[]): { [basePath: string return result; } -function isEqualRequests(r1: IWatcherRequest[], r2: IWatcherRequest[]) { - if (r1.length !== r2.length) { - return false; - } - for (let k = 0; k < r1.length; k++) { - if (r1[k].path !== r2[k].path || !isEqualIgnore(r1[k].excludes, r2[k].excludes)) { - return false; - } - } - return true; +function isEqualRequests(r1: readonly IWatcherRequest[], r2: readonly IWatcherRequest[]) { + return equals(r1, r2, (a, b) => a.path === b.path && isEqualIgnore(a.excludes, b.excludes)); } function isEqualIgnore(i1: readonly string[], i2: readonly string[]) { diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index c408e75c739..567bc8e9db8 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -81,17 +81,11 @@ export async function resolveCommonProperties( return result; } -function verifyMicrosoftInternalDomain(domainList: string[]): boolean { +function verifyMicrosoftInternalDomain(domainList: readonly string[]): boolean { if (!process || !process.env || !process.env['USERDNSDOMAIN']) { return false; } const domain = process.env['USERDNSDOMAIN']!.toLowerCase(); - for (let msftDomain of domainList) { - if (domain === msftDomain) { - return true; - } - } - - return false; + return domainList.some(msftDomain => domain === msftDomain); } diff --git a/src/vs/platform/workspaces/common/workspaces.ts b/src/vs/platform/workspaces/common/workspaces.ts index 974a8c87527..3c09c3a7259 100644 --- a/src/vs/platform/workspaces/common/workspaces.ts +++ b/src/vs/platform/workspaces/common/workspaces.ts @@ -294,12 +294,7 @@ function doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace { export function useSlashForPath(storedFolders: IStoredWorkspaceFolder[]): boolean { if (isWindows) { - for (const folder of storedFolders) { - if (isRawFileWorkspaceFolder(folder) && folder.path.indexOf(SLASH) >= 0) { - return true; - } - } - return false; + return storedFolders.some(folder => isRawFileWorkspaceFolder(folder) && folder.path.indexOf(SLASH) >= 0); } return true; } diff --git a/src/vs/workbench/api/browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/browser/mainThreadSaveParticipant.ts index c849ba99630..9bf1db3fe1c 100644 --- a/src/vs/workbench/api/browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/browser/mainThreadSaveParticipant.ts @@ -50,7 +50,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { if (this.configurationService.getValue('files.trimTrailingWhitespace', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doTrimTrailingWhitespace(model.textEditorModel, env.reason === SaveReason.AUTO); } @@ -112,7 +112,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doInsertFinalNewLine(model.textEditorModel); } @@ -146,7 +146,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant // Nothing } - async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { if (this.configurationService.getValue('files.trimFinalNewlines', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doTrimFinalNewLines(model.textEditorModel, env.reason === SaveReason.AUTO); } @@ -216,7 +216,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { const model = editorModel.textEditorModel; const overrides = { overrideIdentifier: model.getLanguageIdentifier().language, resource: model.uri }; @@ -250,7 +250,7 @@ class CodeActionOnSaveParticipant implements ISaveParticipant { @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { } - async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { if (env.reason === SaveReason.AUTO) { return undefined; } @@ -333,7 +333,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant); } - async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { if (!shouldSynchronizeModel(editorModel.textEditorModel)) { // the model never made it to the extension @@ -344,10 +344,8 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant { return new Promise((resolve, reject) => { setTimeout(() => reject(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms")), 1750); this._proxy.$participateInSave(editorModel.getResource(), env.reason).then(values => { - for (const success of values) { - if (!success) { - return Promise.reject(new Error('listener failed')); - } + if (!values.every(success => success)) { + return Promise.reject(new Error('listener failed')); } return undefined; }).then(resolve, reject); @@ -384,7 +382,7 @@ export class SaveParticipant implements ISaveParticipant { this._saveParticipants.dispose(); } - async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise { return this._progressService.withProgress({ location: ProgressLocation.Window }, progress => { progress.report({ message: localize('saveParticipants', "Running Save Participants...") }); const promiseFactory = this._saveParticipants.getValue().map(p => () => { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 28b7f5ae205..27c39b9f121 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -614,12 +614,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit { } has(uri: URI): boolean { - for (const edit of this._edits) { - if (edit._type === 2 && edit.uri.toString() === uri.toString()) { - return true; - } - } - return false; + return this._edits.some(edit => edit._type === 2 && edit.uri.toString() === uri.toString()); } set(uri: URI, edits: TextEdit[]): void { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index eb76fe7dbd4..ac4ff59a817 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -273,13 +273,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { return false; } - for (let extensionId of extensionFilters) { - if (extensionId.toLowerCase() === this.setting.extensionInfo.id.toLowerCase()) { - return true; - } - } - - return false; + return Array.from(extensionFilters).some(extensionId => extensionId.toLowerCase() === this.setting.extensionInfo!.id.toLowerCase()); } } @@ -409,7 +403,7 @@ function sanitizeId(id: string): string { return id.replace(/[\.\/]/, '_'); } -export function settingKeyToDisplayFormat(key: string, groupId = ''): { category: string, label: string } { +export function settingKeyToDisplayFormat(key: string, groupId = ''): { category: string, label: string; } { const lastDotIdx = key.lastIndexOf('.'); let category = ''; if (lastDotIdx >= 0) { From 095358e3b2785594179fd7e6298086aef23c7c0c Mon Sep 17 00:00:00 2001 From: U-ways Date: Mon, 7 Oct 2019 22:48:49 +0100 Subject: [PATCH 256/435] fix image preview to show correct canvas size when editor is scaled down vertically (#82027) See issue #81878 --- extensions/image-preview/media/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/image-preview/media/main.css b/extensions/image-preview/media/main.css index 913d2b46726..0f50cef683c 100644 --- a/extensions/image-preview/media/main.css +++ b/extensions/image-preview/media/main.css @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ html, body { + width: 100%; height: 100%; - max-height: 100%; text-align: center; } From 90f33ddc6dacb25a2c54135e5914dfea86f440f3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 15:07:49 -0700 Subject: [PATCH 257/435] Use DisposableStore in a few more places - Also switches a few places that re-implemented Disposable with calls to `_register` instead --- src/vs/base/browser/ui/tree/asyncDataTree.ts | 8 ++-- src/vs/platform/list/browser/listService.ts | 8 ++-- .../electron-main/updateService.darwin.ts | 6 +-- .../api/common/extHostApiCommands.ts | 6 +-- .../api/common/menusExtensionPoint.ts | 8 ++-- src/vs/workbench/browser/parts/views/views.ts | 40 +++++++++---------- .../contrib/debug/browser/debugActions.ts | 39 +++++++----------- .../extensions/browser/extensionsViewer.ts | 2 +- .../preferences/browser/preferencesActions.ts | 14 ++----- 9 files changed, 56 insertions(+), 75 deletions(-) diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index 4cf442d26df..e7514bfabe6 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -7,7 +7,7 @@ import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree'; import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list'; import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper } from 'vs/base/browser/ui/tree/tree'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { IListStyles } from 'vs/base/browser/ui/list/listWidget'; @@ -88,7 +88,6 @@ class AsyncDataTreeRenderer implements IT readonly templateId: string; private renderedNodes = new Map, IDataTreeListTemplateData>(); - private disposables: IDisposable[] = []; constructor( protected renderer: ITreeRenderer, @@ -124,7 +123,6 @@ class AsyncDataTreeRenderer implements IT dispose(): void { this.renderedNodes.clear(); - this.disposables = dispose(this.disposables); } } @@ -292,7 +290,7 @@ export class AsyncDataTree implements IDisposable protected readonly nodeMapper: AsyncDataTreeNodeMapper = new WeakMapper(node => new AsyncDataTreeNodeWrapper(node)); - protected readonly disposables: IDisposable[] = []; + protected readonly disposables = new DisposableStore(); get onDidScroll(): Event { return this.tree.onDidScroll; } @@ -930,7 +928,7 @@ export class AsyncDataTree implements IDisposable } dispose(): void { - dispose(this.disposables); + this.disposables.dispose(); } } diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index e70bf539f65..c0a6c5b2c0d 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -881,9 +881,9 @@ export class WorkbenchAsyncDataTree extends Async ) { const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService); super(user, container, delegate, renderers, dataSource, treeOptions); - this.disposables.push(disposable); + this.disposables.add(disposable); this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService); - this.disposables.push(this.internals); + this.disposables.add(this.internals); } } @@ -910,9 +910,9 @@ export class WorkbenchCompressibleAsyncDataTree e ) { const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService); super(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, treeOptions); - this.disposables.push(disposable); + this.disposables.add(disposable); this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService); - this.disposables.push(this.internals); + this.disposables.add(this.internals); } } diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts index cd73a5cd95a..d25c577b66e 100644 --- a/src/vs/platform/update/electron-main/updateService.darwin.ts +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as electron from 'electron'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; import { memoize } from 'vs/base/common/decorators'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -20,7 +20,7 @@ export class DarwinUpdateService extends AbstractUpdateService { _serviceBrand: undefined; - private disposables: IDisposable[] = []; + private readonly disposables = new DisposableStore(); @memoize private get onRawError(): Event { return Event.fromNodeEventEmitter(electron.autoUpdater, 'error', (_, message) => message); } @memoize private get onRawUpdateNotAvailable(): Event { return Event.fromNodeEventEmitter(electron.autoUpdater, 'update-not-available'); } @@ -104,6 +104,6 @@ export class DarwinUpdateService extends AbstractUpdateService { } dispose(): void { - this.disposables = dispose(this.disposables); + this.disposables.dispose(); } } diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index 1cf22a6fad6..ff8f8cebe65 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import * as vscode from 'vscode'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import * as types from 'vs/workbench/api/common/extHostTypes'; @@ -27,7 +27,7 @@ export class ExtHostApiCommands { } private _commands: ExtHostCommands; - private _disposables: IDisposable[] = []; + private readonly _disposables = new DisposableStore(); private constructor(commands: ExtHostCommands) { this._commands = commands; @@ -288,7 +288,7 @@ export class ExtHostApiCommands { private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void { const disposable = this._commands.registerCommand(false, id, handler, this, description); - this._disposables.push(disposable); + this._disposables.add(disposable); } /** diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index 0dd6facb692..3133acfba2c 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -12,7 +12,7 @@ import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } fr import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { MenuId, MenuRegistry, ILocalizedString, IMenuItem } from 'vs/platform/actions/common/actions'; import { URI } from 'vs/base/common/uri'; -import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; namespace schema { @@ -387,7 +387,7 @@ commandsExtensionPoint.setHandler(extensions => { } }); -let _menuRegistrations: IDisposable[] = []; +const _menuRegistrations = new DisposableStore(); ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyMenuItem[] }>({ extensionPoint: 'menus', @@ -395,7 +395,7 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM }).setHandler(extensions => { // remove all previous menu registrations - _menuRegistrations = dispose(_menuRegistrations); + _menuRegistrations.clear(); for (let extension of extensions) { const { value, collector } = extension; @@ -450,7 +450,7 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM order, when: ContextKeyExpr.deserialize(item.when) } as IMenuItem); - _menuRegistrations.push(registration); + _menuRegistrations.add(registration); } }); } diff --git a/src/vs/workbench/browser/parts/views/views.ts b/src/vs/workbench/browser/parts/views/views.ts index 87c08909cff..9a0a307dd5c 100644 --- a/src/vs/workbench/browser/parts/views/views.ts +++ b/src/vs/workbench/browser/parts/views/views.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/views'; -import { Disposable, IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IViewsService, IViewsViewlet, ViewContainer, IViewDescriptor, IViewContainersRegistry, Extensions as ViewExtensions, IView, IViewDescriptorCollection, IViewsRegistry } from 'vs/workbench/common/views'; import { Registry } from 'vs/platform/registry/common/platform'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -22,14 +22,14 @@ import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/th import { toggleClass, addClass } from 'vs/base/browser/dom'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -function filterViewRegisterEvent(container: ViewContainer, event: Event<{ viewContainer: ViewContainer, views: IViewDescriptor[] }>): Event { +function filterViewRegisterEvent(container: ViewContainer, event: Event<{ viewContainer: ViewContainer, views: IViewDescriptor[]; }>): Event { return Event.chain(event) .map(({ views, viewContainer }) => viewContainer === container ? views : []) .filter(views => views.length > 0) .event; } -function filterViewMoveEvent(container: ViewContainer, event: Event<{ from: ViewContainer, to: ViewContainer, views: IViewDescriptor[] }>): Event<{ added?: IViewDescriptor[], removed?: IViewDescriptor[] }> { +function filterViewMoveEvent(container: ViewContainer, event: Event<{ from: ViewContainer, to: ViewContainer, views: IViewDescriptor[]; }>): Event<{ added?: IViewDescriptor[], removed?: IViewDescriptor[]; }> { return Event.chain(event) .map(({ views, from, to }) => from === container ? { removed: views } : to === container ? { added: views } : {}) .filter(({ added, removed }) => isNonEmptyArray(added) || isNonEmptyArray(removed)) @@ -78,8 +78,8 @@ class ViewDescriptorCollection extends Disposable implements IViewDescriptorColl private contextKeys = new CounterSet(); private items: IViewItem[] = []; - private _onDidChange: Emitter<{ added: IViewDescriptor[], removed: IViewDescriptor[] }> = this._register(new Emitter<{ added: IViewDescriptor[], removed: IViewDescriptor[] }>()); - readonly onDidChangeActiveViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[] }> = this._onDidChange.event; + private _onDidChange: Emitter<{ added: IViewDescriptor[], removed: IViewDescriptor[]; }> = this._register(new Emitter<{ added: IViewDescriptor[], removed: IViewDescriptor[]; }>()); + readonly onDidChangeActiveViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[]; }> = this._onDidChange.event; get activeViewDescriptors(): IViewDescriptor[] { return this.items @@ -356,7 +356,7 @@ export class ContributableViewsModel extends Disposable { return viewDescriptor.workspace ? !!viewState.visibleWorkspace : !!viewState.visibleGlobal; } - private find(id: string): { index: number, visibleIndex: number, viewDescriptor: IViewDescriptor, state: IViewState } { + private find(id: string): { index: number, visibleIndex: number, viewDescriptor: IViewDescriptor, state: IViewState; } { for (let i = 0, visibleIndex = 0; i < this.viewDescriptors.length; i++) { const viewDescriptor = this.viewDescriptors[i]; const state = this.viewStates.get(viewDescriptor.id); @@ -436,8 +436,8 @@ export class ContributableViewsModel extends Disposable { (a, b) => a.id === b.id ? 0 : a.id < b.id ? -1 : 1 ).reverse(); - const toRemove: { index: number, viewDescriptor: IViewDescriptor }[] = []; - const toAdd: { index: number, viewDescriptor: IViewDescriptor, size?: number, collapsed: boolean }[] = []; + const toRemove: { index: number, viewDescriptor: IViewDescriptor; }[] = []; + const toAdd: { index: number, viewDescriptor: IViewDescriptor, size?: number, collapsed: boolean; }[] = []; for (const splice of splices) { const startViewDescriptor = this.viewDescriptors[splice.start]; @@ -521,7 +521,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel { } private saveWorkspaceViewsStates(): void { - const storedViewsStates: { [id: string]: IStoredWorkspaceViewState } = JSON.parse(this.storageService.get(this.workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); + const storedViewsStates: { [id: string]: IStoredWorkspaceViewState; } = JSON.parse(this.storageService.get(this.workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); for (const viewDescriptor of this.viewDescriptors) { const viewState = this.viewStates.get(viewDescriptor.id); if (viewState) { @@ -557,7 +557,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel { private static loadViewsStates(workspaceViewsStateStorageId: string, globalViewsStateStorageId: string, storageService: IStorageService): Map { const viewStates = new Map(); - const workspaceViewsStates = <{ [id: string]: IStoredWorkspaceViewState }>JSON.parse(storageService.get(workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); + const workspaceViewsStates = <{ [id: string]: IStoredWorkspaceViewState; }>JSON.parse(storageService.get(workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); for (const id of Object.keys(workspaceViewsStates)) { const workspaceViewState = workspaceViewsStates[id]; viewStates.set(id, { @@ -636,7 +636,7 @@ export class ViewsService extends Disposable implements IViewsService { _serviceBrand: undefined; - private readonly viewDescriptorCollections: Map; + private readonly viewDescriptorCollections: Map; private readonly viewDisposable: Map; private readonly activeViewContextKeys: Map>; @@ -646,7 +646,7 @@ export class ViewsService extends Disposable implements IViewsService { ) { super(); - this.viewDescriptorCollections = new Map(); + this.viewDescriptorCollections = new Map(); this.viewDisposable = new Map(); this.activeViewContextKeys = new Map>(); @@ -692,13 +692,13 @@ export class ViewsService extends Disposable implements IViewsService { } private onDidRegisterViewContainer(viewContainer: ViewContainer): void { - const viewDescriptorCollection = new ViewDescriptorCollection(viewContainer, this.contextKeyService); - const disposables: IDisposable[] = [viewDescriptorCollection]; + const disposables = new DisposableStore(); + const viewDescriptorCollection = disposables.add(new ViewDescriptorCollection(viewContainer, this.contextKeyService)); this.onDidChangeActiveViews({ added: viewDescriptorCollection.activeViewDescriptors, removed: [] }); viewDescriptorCollection.onDidChangeActiveViews(changed => this.onDidChangeActiveViews(changed), this, disposables); - this.viewDescriptorCollections.set(viewContainer, { viewDescriptorCollection, disposable: toDisposable(() => dispose(disposables)) }); + this.viewDescriptorCollections.set(viewContainer, { viewDescriptorCollection, disposable: disposables }); } private onDidDeregisterViewContainer(viewContainer: ViewContainer): void { @@ -709,7 +709,7 @@ export class ViewsService extends Disposable implements IViewsService { } } - private onDidChangeActiveViews({ added, removed }: { added: IViewDescriptor[], removed: IViewDescriptor[] }): void { + private onDidChangeActiveViews({ added, removed }: { added: IViewDescriptor[], removed: IViewDescriptor[]; }): void { added.forEach(viewDescriptor => this.getOrCreateActiveViewContextKey(viewDescriptor).set(true)); removed.forEach(viewDescriptor => this.getOrCreateActiveViewContextKey(viewDescriptor).set(false)); } @@ -717,7 +717,7 @@ export class ViewsService extends Disposable implements IViewsService { private onDidRegisterViews(container: ViewContainer, views: IViewDescriptor[]): void { const viewlet = this.viewletService.getViewlet(container.id); for (const viewDescriptor of views) { - const disposables: IDisposable[] = []; + const disposables = new DisposableStore(); const command: ICommandAction = { id: viewDescriptor.focusCommand ? viewDescriptor.focusCommand.id : `${viewDescriptor.id}.focus`, title: { original: `Focus on ${viewDescriptor.name} View`, value: localize('focus view', "Focus on {0} View", viewDescriptor.name) }, @@ -725,9 +725,9 @@ export class ViewsService extends Disposable implements IViewsService { }; const when = ContextKeyExpr.has(`${viewDescriptor.id}.active`); - disposables.push(CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true))); + disposables.add(CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true))); - disposables.push(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { + disposables.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command, when })); @@ -745,7 +745,7 @@ export class ViewsService extends Disposable implements IViewsService { }); } - this.viewDisposable.set(viewDescriptor, toDisposable(() => dispose(disposables))); + this.viewDisposable.set(viewDescriptor, disposables); } } diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 1ecdb87c297..6f5605d3078 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -15,20 +15,16 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { startDebugging } from 'vs/workbench/contrib/debug/common/debugUtils'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; export abstract class AbstractDebugAction extends Action { - protected toDispose: IDisposable[]; - constructor( id: string, label: string, cssClass: string, @IDebugService protected debugService: IDebugService, @IKeybindingService protected keybindingService: IKeybindingService, ) { super(id, label, cssClass, false); - this.toDispose = []; - this.toDispose.push(this.debugService.onDidChangeState(state => this.updateEnablement(state))); + this._register(this.debugService.onDidChangeState(state => this.updateEnablement(state))); this.updateLabel(label); this.updateEnablement(); @@ -56,11 +52,6 @@ export abstract class AbstractDebugAction extends Action { protected isEnabled(_: State): boolean { return true; } - - dispose(): void { - super.dispose(); - this.toDispose = dispose(this.toDispose); - } } export class ConfigureAction extends AbstractDebugAction { @@ -74,7 +65,7 @@ export class ConfigureAction extends AbstractDebugAction { @IWorkspaceContextService private readonly contextService: IWorkspaceContextService ) { super(id, label, 'debug-action configure', debugService, keybindingService); - this.toDispose.push(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass())); + this._register(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass())); this.updateClass(); } @@ -120,10 +111,10 @@ export class StartAction extends AbstractDebugAction { ) { super(id, label, 'debug-action start', debugService, keybindingService); - this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement())); - this.toDispose.push(this.debugService.onDidNewSession(() => this.updateEnablement())); - this.toDispose.push(this.debugService.onDidEndSession(() => this.updateEnablement())); - this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement())); + this._register(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement())); + this._register(this.debugService.onDidNewSession(() => this.updateEnablement())); + this._register(this.debugService.onDidEndSession(() => this.updateEnablement())); + this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement())); } run(): Promise { @@ -200,7 +191,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action remove-all', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } run(): Promise { @@ -219,7 +210,7 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action enable-all-breakpoints', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } run(): Promise { @@ -238,7 +229,7 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action disable-all-breakpoints', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } run(): Promise { @@ -260,7 +251,7 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { super(id, label, 'debug-action breakpoints-activate', debugService, keybindingService); this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => { + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => { this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL); this.updateEnablement(); })); @@ -281,7 +272,7 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, '', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } run(): Promise { @@ -301,7 +292,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action add-function-breakpoint', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement())); } run(): Promise { @@ -321,8 +312,8 @@ export class AddWatchExpressionAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action add-watch-expression', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); - this.toDispose.push(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); + this._register(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement())); } run(): Promise { @@ -342,7 +333,7 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action remove-all', debugService, keybindingService); - this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); + this._register(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement())); } run(): Promise { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts index 919c3762319..41bb90eb632 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts @@ -213,7 +213,7 @@ export class ExtensionsTree extends WorkbenchAsyncDataTree { + this.disposables.add(this.onDidChangeSelection(event => { if (event.browserEvent && event.browserEvent instanceof KeyboardEvent) { extensionsWorkdbenchService.open(event.elements[0].extension, false); } diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts index b93c9b2fd62..b7742712238 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Action } from 'vs/base/common/actions'; -import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -198,9 +198,6 @@ export class OpenFolderSettingsAction extends Action { static readonly ID = 'workbench.action.openFolderSettings'; static readonly LABEL = OPEN_FOLDER_SETTINGS_LABEL; - private disposables: IDisposable[] = []; - - constructor( id: string, label: string, @@ -210,8 +207,8 @@ export class OpenFolderSettingsAction extends Action { ) { super(id, label); this.update(); - this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables); - this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.update(), this, this.disposables); + this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this)); + this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.update(), this)); } private update(): void { @@ -228,11 +225,6 @@ export class OpenFolderSettingsAction extends Action { return undefined; }); } - - dispose(): void { - this.disposables = dispose(this.disposables); - super.dispose(); - } } export class ConfigureLanguageBasedSettingsAction extends Action { From b0dccbcf75fd03ac8cc0fa94da5c552a4f47309d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 15:39:21 -0700 Subject: [PATCH 258/435] Marking a bunch of static variables as readonly Readonly helps out with TS's type guards and is also a good best practice. Specifically, readonly strings/numbers have their literal type instead of a generic `string` | `number` type, which can help catch dead code and some common programming mistakes --- src/vs/base/browser/touch.ts | 2 +- src/vs/base/browser/ui/tree/abstractTree.ts | 2 +- src/vs/base/common/lifecycle.ts | 2 +- .../ipc/electron-main/ipc.electron-main.ts | 2 +- src/vs/base/parts/storage/node/storage.ts | 6 +- src/vs/base/parts/tree/browser/treeView.ts | 4 +- src/vs/code/browser/workbench/workbench.ts | 6 +- .../contrib/storageDataCleaner.ts | 2 +- .../editor/browser/controller/mouseHandler.ts | 2 +- .../browser/controller/textAreaHandler.ts | 2 +- .../viewParts/viewCursors/viewCursors.ts | 2 +- .../editor/browser/widget/diffEditorWidget.ts | 2 +- src/vs/editor/common/controller/cursor.ts | 2 +- src/vs/editor/common/core/rgba.ts | 2 +- .../contrib/colorPicker/colorDetector.ts | 2 +- src/vs/editor/contrib/dnd/dnd.ts | 2 +- .../contrib/documentSymbols/outlineTree.ts | 4 +- src/vs/editor/contrib/folding/folding.ts | 2 +- .../contrib/folding/foldingDecorations.ts | 6 +- .../goToDefinition/goToDefinitionMouse.ts | 2 +- src/vs/editor/contrib/links/links.ts | 2 +- .../contrib/message/messageController.ts | 2 +- .../contrib/snippet/snippetController2.ts | 6 +- .../contrib/suggest/suggestAlternatives.ts | 2 +- .../standalone/browser/simpleServices.ts | 2 +- .../contextkey/browser/contextKeyService.ts | 2 +- .../common/instantiationService.ts | 2 +- src/vs/platform/state/node/stateService.ts | 2 +- src/vs/platform/storage/node/storageIpc.ts | 2 +- .../storage/node/storageMainService.ts | 2 +- .../platform/storage/node/storageService.ts | 4 +- .../telemetry/common/telemetryService.ts | 4 +- src/vs/workbench/api/common/apiCommands.ts | 14 ++-- .../workbench/api/common/extHostTreeViews.ts | 4 +- .../browser/actions/developerActions.ts | 6 +- .../browser/actions/layoutActions.ts | 4 +- .../browser/actions/windowActions.ts | 6 +- .../browser/actions/workspaceActions.ts | 14 ++-- .../parts/activitybar/activitybarActions.ts | 4 +- .../browser/parts/editor/breadcrumbs.ts | 14 ++-- .../parts/editor/breadcrumbsControl.ts | 8 +-- .../browser/parts/editor/editorDropTarget.ts | 2 +- .../notifications/notificationsCenter.ts | 2 +- .../notifications/notificationsToasts.ts | 4 +- .../browser/parts/panel/panelActions.ts | 8 +-- .../browser/parts/quickinput/quickInput.ts | 4 +- .../browser/parts/titlebar/menubarControl.ts | 2 +- .../browser/parts/views/panelViewlet.ts | 2 +- src/vs/workbench/common/notifications.ts | 6 +- src/vs/workbench/common/resources.ts | 14 ++-- .../browser/callHierarchy.contribution.ts | 4 +- .../browser/callHierarchyTree.ts | 2 +- .../contrib/cli/node/cli.contribution.ts | 4 +- .../codeEditor/browser/selectionClipboard.ts | 2 +- .../comments/browser/commentsTreeViewer.ts | 4 +- .../contrib/debug/browser/debugActions.ts | 28 ++++---- .../debug/browser/debugEditorActions.ts | 4 +- .../contrib/debug/browser/debugHover.ts | 2 +- .../contrib/debug/browser/debugViewlet.ts | 2 +- .../debug/browser/loadedScriptsView.ts | 2 +- .../workbench/contrib/debug/browser/repl.ts | 4 +- .../contrib/debug/common/debugModel.ts | 4 +- .../extensions/browser/extensionsActions.ts | 70 +++++++++---------- .../electron-browser/extensionsActions.ts | 2 +- .../runtimeExtensionsEditor.ts | 14 ++-- .../files/browser/views/openEditorsView.ts | 2 +- .../format/browser/formatActionsMultiple.ts | 2 +- .../contrib/logs/common/logsActions.ts | 8 +-- .../logs/electron-browser/logsActions.ts | 4 +- .../contrib/output/browser/outputActions.ts | 8 +-- .../preferences/browser/settingsTreeModels.ts | 2 +- .../contrib/remote/browser/remote.ts | 2 +- .../contrib/scm/browser/repositoryPanel.ts | 4 +- .../contrib/scm/browser/scm.contribution.ts | 2 +- .../contrib/search/browser/searchActions.ts | 2 +- .../contrib/snippets/browser/tabCompletion.ts | 2 +- .../tasks/browser/terminalTaskSystem.ts | 2 +- .../themes/browser/themes.contribution.ts | 8 +-- .../contrib/update/browser/update.ts | 2 +- .../contrib/webview/browser/webviewEditor.ts | 2 +- .../browser/telemetryOptOut.ts | 2 +- .../actions/developerActions.ts | 4 +- .../electron-browser/actions/windowActions.ts | 6 +- .../actions/workspaceActions.ts | 2 +- .../electron-browser/clipboardService.ts | 2 +- .../browser/configurationResolverService.ts | 2 +- .../common/variableResolver.ts | 4 +- .../services/extensions/common/rpcProtocol.ts | 2 +- .../output/common/outputChannelModel.ts | 2 +- .../test/textFileEditorModelManager.test.ts | 2 +- 90 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/vs/base/browser/touch.ts b/src/vs/base/browser/touch.ts index 4519d7e0e16..bef90a94d4d 100644 --- a/src/vs/base/browser/touch.ts +++ b/src/vs/base/browser/touch.ts @@ -67,7 +67,7 @@ export class Gesture extends Disposable { private static readonly SCROLL_FRICTION = -0.005; private static INSTANCE: Gesture; - private static HOLD_DELAY = 700; + private static readonly HOLD_DELAY = 700; private dispatched = false; private targets: HTMLElement[]; diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 68754b3e448..925a9128552 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -238,7 +238,7 @@ class EventCollection implements Collection { class TreeRenderer implements IListRenderer, ITreeListTemplateData> { - private static DefaultIndent = 8; + private static readonly DefaultIndent = 8; readonly templateId: string; private renderedElements = new Map>(); diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 44cfdada8ab..8d1cbd5b996 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -138,7 +138,7 @@ export class DisposableStore implements IDisposable { export abstract class Disposable implements IDisposable { - static None = Object.freeze({ dispose() { } }); + static readonly None = Object.freeze({ dispose() { } }); private readonly _store = new DisposableStore(); diff --git a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts index b310a886f67..bac2223ede6 100644 --- a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts +++ b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts @@ -23,7 +23,7 @@ function createScopedOnMessageEvent(senderId: number, eventName: string): Event< export class Server extends IPCServer { - private static Clients = new Map(); + private static readonly Clients = new Map(); private static getOnDidClientConnect(): Event { const onHello = Event.fromNodeEventEmitter(ipcMain, 'ipc:hello', ({ sender }) => sender); diff --git a/src/vs/base/parts/storage/node/storage.ts b/src/vs/base/parts/storage/node/storage.ts index 5042879c655..e73aafe6ad4 100644 --- a/src/vs/base/parts/storage/node/storage.ts +++ b/src/vs/base/parts/storage/node/storage.ts @@ -32,12 +32,12 @@ export interface ISQLiteStorageDatabaseLoggingOptions { export class SQLiteStorageDatabase implements IStorageDatabase { - static IN_MEMORY_PATH = ':memory:'; + static readonly IN_MEMORY_PATH = ':memory:'; get onDidChangeItemsExternal(): Event { return Event.None; } // since we are the only client, there can be no external changes - private static BUSY_OPEN_TIMEOUT = 2000; // timeout in ms to retry when opening DB fails with SQLITE_BUSY - private static MAX_HOST_PARAMETERS = 256; // maximum number of parameters within a statement + private static readonly BUSY_OPEN_TIMEOUT = 2000; // timeout in ms to retry when opening DB fails with SQLITE_BUSY + private static readonly MAX_HOST_PARAMETERS = 256; // maximum number of parameters within a statement private path: string; private name: string; diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index bdd8f7da8e8..e1c832eacb7 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -398,8 +398,8 @@ function reactionEquals(one: _.IDragOverReaction, other: _.IDragOverReaction | n export class TreeView extends HeightMap { - static BINDING = 'monaco-tree-row'; - static LOADING_DECORATION_DELAY = 800; + static readonly BINDING = 'monaco-tree-row'; + static readonly LOADING_DECORATION_DELAY = 800; private static counter: number = 0; private instance: number; diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 60e7d9a3ecc..1f0384a7424 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -103,10 +103,10 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider { class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvider { - static FETCH_INTERVAL = 500; // fetch every 500ms - static FETCH_TIMEOUT = 5 * 60 * 1000; // ...but stop after 5min + static readonly FETCH_INTERVAL = 500; // fetch every 500ms + static readonly FETCH_TIMEOUT = 5 * 60 * 1000; // ...but stop after 5min - static QUERY_KEYS = { + static readonly QUERY_KEYS = { REQUEST_ID: 'vscode-requestId', SCHEME: 'vscode-scheme', AUTHORITY: 'vscode-authority', diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts index d3a0e9dab87..a3899b854fb 100644 --- a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts +++ b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts @@ -13,7 +13,7 @@ import { IBackupWorkspacesFormat } from 'vs/platform/backup/node/backup'; export class StorageDataCleaner extends Disposable { // Workspace/Folder storage names are MD5 hashes (128bits / 4 due to hex presentation) - private static NON_EMPTY_WORKSPACE_ID_LENGTH = 128 / 4; + private static readonly NON_EMPTY_WORKSPACE_ID_LENGTH = 128 / 4; constructor( @IEnvironmentService private readonly environmentService: IEnvironmentService diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index dd8979daabc..357f1f542be 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -65,7 +65,7 @@ export interface IPointerHandlerHelper { export class MouseHandler extends ViewEventHandler { - static MOUSE_MOVE_MINIMUM_TIME = 100; // ms + static readonly MOUSE_MOVE_MINIMUM_TIME = 100; // ms protected _context: ViewContext; protected viewController: ViewController; diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 7d5cab28c98..2a734c4adc8 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -66,7 +66,7 @@ interface LocalClipboardMetadata { * we can fetch the previous metadata. */ class LocalClipboardMetadataManager { - public static INSTANCE = new LocalClipboardMetadataManager(); + public static readonly INSTANCE = new LocalClipboardMetadataManager(); private _lastState: LocalClipboardMetadata | null; diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index c60e020b56f..a703cbafd2b 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -18,7 +18,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic export class ViewCursors extends ViewPart { - static BLINK_INTERVAL = 500; + static readonly BLINK_INTERVAL = 500; private _readOnly: boolean; private _cursorBlinking: TextEditorCursorBlinkingStyle; diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index ef815de2219..f6b8b30bb9c 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1562,7 +1562,7 @@ const DECORATIONS = { class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEditorWidgetStyle, IVerticalSashLayoutProvider { - static MINIMUM_EDITOR_WIDTH = 100; + static readonly MINIMUM_EDITOR_WIDTH = 100; private _disableSash: boolean; private readonly _sash: Sash; diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 4b4fb9cc473..95be4c66153 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -141,7 +141,7 @@ class AutoClosedAction { export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { - public static MAX_CURSOR_COUNT = 10000; + public static readonly MAX_CURSOR_COUNT = 10000; private readonly _onDidReachMaxCursorCount: Emitter = this._register(new Emitter()); public readonly onDidReachMaxCursorCount: Event = this._onDidReachMaxCursorCount.event; diff --git a/src/vs/editor/common/core/rgba.ts b/src/vs/editor/common/core/rgba.ts index 0ce94359f31..3a19425bc4d 100644 --- a/src/vs/editor/common/core/rgba.ts +++ b/src/vs/editor/common/core/rgba.ts @@ -10,7 +10,7 @@ export class RGBA8 { _rgba8Brand: void; - static Empty = new RGBA8(0, 0, 0, 0); + static readonly Empty = new RGBA8(0, 0, 0, 0); /** * Red: integer in [0-255] diff --git a/src/vs/editor/contrib/colorPicker/colorDetector.ts b/src/vs/editor/contrib/colorPicker/colorDetector.ts index c1460b7650d..7e2b9e03de4 100644 --- a/src/vs/editor/contrib/colorPicker/colorDetector.ts +++ b/src/vs/editor/contrib/colorPicker/colorDetector.ts @@ -27,7 +27,7 @@ export class ColorDetector extends Disposable implements IEditorContribution { private static readonly ID: string = 'editor.contrib.colorDetector'; - static RECOMPUTE_TIME = 1000; // ms + static readonly RECOMPUTE_TIME = 1000; // ms private readonly _localToDispose = this._register(new DisposableStore()); private _computePromise: CancelablePromise | null; diff --git a/src/vs/editor/contrib/dnd/dnd.ts b/src/vs/editor/contrib/dnd/dnd.ts index bbf3df37d01..044ea027dc3 100644 --- a/src/vs/editor/contrib/dnd/dnd.ts +++ b/src/vs/editor/contrib/dnd/dnd.ts @@ -38,7 +38,7 @@ export class DragAndDropController extends Disposable implements editorCommon.IE private _dndDecorationIds: string[]; private _mouseDown: boolean; private _modifierPressed: boolean; - static TRIGGER_KEY_VALUE = isMacintosh ? KeyCode.Alt : KeyCode.Ctrl; + static readonly TRIGGER_KEY_VALUE = isMacintosh ? KeyCode.Alt : KeyCode.Ctrl; static get(editor: ICodeEditor): DragAndDropController { return editor.getContribution(DragAndDropController.ID); diff --git a/src/vs/editor/contrib/documentSymbols/outlineTree.ts b/src/vs/editor/contrib/documentSymbols/outlineTree.ts index 84ac8bb704c..4b96ccf9240 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineTree.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineTree.ts @@ -44,7 +44,7 @@ export class OutlineIdentityProvider implements IIdentityProvider { } export class OutlineGroupTemplate { - static id = 'OutlineGroupTemplate'; + static readonly id = 'OutlineGroupTemplate'; constructor( readonly labelContainer: HTMLElement, readonly label: HighlightedLabel, @@ -52,7 +52,7 @@ export class OutlineGroupTemplate { } export class OutlineElementTemplate { - static id = 'OutlineElementTemplate'; + static readonly id = 'OutlineElementTemplate'; constructor( readonly container: HTMLElement, readonly iconLabel: IconLabel, diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index eb550be02fb..87fa92fb892 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -50,7 +50,7 @@ interface FoldingStateMemento { export class FoldingController extends Disposable implements IEditorContribution { - static MAX_FOLDING_REGIONS = 5000; + static readonly MAX_FOLDING_REGIONS = 5000; public static get(editor: ICodeEditor): FoldingController { diff --git a/src/vs/editor/contrib/folding/foldingDecorations.ts b/src/vs/editor/contrib/folding/foldingDecorations.ts index 44554ac1300..333ad459db0 100644 --- a/src/vs/editor/contrib/folding/foldingDecorations.ts +++ b/src/vs/editor/contrib/folding/foldingDecorations.ts @@ -10,18 +10,18 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; export class FoldingDecorationProvider implements IDecorationProvider { - private static COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static readonly COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, afterContentClassName: 'inline-folded', linesDecorationsClassName: 'codicon codicon-chevron-right' }); - private static EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static readonly EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, linesDecorationsClassName: 'codicon codicon-chevron-down' }); - private static EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static readonly EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, linesDecorationsClassName: 'codicon codicon-chevron-down alwaysShowFoldIcons' }); diff --git a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts index 7d0dd7ce4e1..589e552e225 100644 --- a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts +++ b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts @@ -30,7 +30,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorContribution { private static readonly ID = 'editor.contrib.gotodefinitionwithmouse'; - static MAX_SOURCE_PREVIEW_LINES = 8; + static readonly MAX_SOURCE_PREVIEW_LINES = 8; private readonly editor: ICodeEditor; private readonly toUnhook = new DisposableStore(); diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 1eee5898a96..a387d6cd9db 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -106,7 +106,7 @@ class LinkDetector implements editorCommon.IEditorContribution { return editor.getContribution(LinkDetector.ID); } - static RECOMPUTE_TIME = 1000; // ms + static readonly RECOMPUTE_TIME = 1000; // ms private readonly editor: ICodeEditor; private enabled: boolean; diff --git a/src/vs/editor/contrib/message/messageController.ts b/src/vs/editor/contrib/message/messageController.ts index e57a0987498..311a922e7da 100644 --- a/src/vs/editor/contrib/message/messageController.ts +++ b/src/vs/editor/contrib/message/messageController.ts @@ -23,7 +23,7 @@ export class MessageController extends Disposable implements editorCommon.IEdito private static readonly _id = 'editor.contrib.messageController'; - static MESSAGE_VISIBLE = new RawContextKey('messageVisible', false); + static readonly MESSAGE_VISIBLE = new RawContextKey('messageVisible', false); static get(editor: ICodeEditor): MessageController { return editor.getContribution(MessageController._id); diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index cec786f46fe..021310ed839 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -44,9 +44,9 @@ export class SnippetController2 implements IEditorContribution { return editor.getContribution('snippetController2'); } - static InSnippetMode = new RawContextKey('inSnippetMode', false); - static HasNextTabstop = new RawContextKey('hasNextTabstop', false); - static HasPrevTabstop = new RawContextKey('hasPrevTabstop', false); + static readonly InSnippetMode = new RawContextKey('inSnippetMode', false); + static readonly HasNextTabstop = new RawContextKey('hasNextTabstop', false); + static readonly HasPrevTabstop = new RawContextKey('hasPrevTabstop', false); private readonly _inSnippet: IContextKey; private readonly _hasNextTabstop: IContextKey; diff --git a/src/vs/editor/contrib/suggest/suggestAlternatives.ts b/src/vs/editor/contrib/suggest/suggestAlternatives.ts index e8a6ea1a338..6c9a148e618 100644 --- a/src/vs/editor/contrib/suggest/suggestAlternatives.ts +++ b/src/vs/editor/contrib/suggest/suggestAlternatives.ts @@ -11,7 +11,7 @@ import { ISelectedSuggestion } from './suggestWidget'; export class SuggestAlternatives { - static OtherSuggestions = new RawContextKey('hasOtherSuggestions', false); + static readonly OtherSuggestions = new RawContextKey('hasOtherSuggestions', false); private readonly _ckOtherSuggestions: IContextKey; diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 372ceb0deab..495b81c11dd 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -551,7 +551,7 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { public _serviceBrand: undefined; - private static SCHEME = 'inmemory'; + private static readonly SCHEME = 'inmemory'; private readonly _onDidChangeWorkspaceName = new Emitter(); public readonly onDidChangeWorkspaceName: Event = this._onDidChangeWorkspaceName.event; diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index d11c36e17ae..41707f15c71 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -87,7 +87,7 @@ class NullContext extends Context { class ConfigAwareContextValuesContainer extends Context { - private static _keyPrefix = 'config.'; + private static readonly _keyPrefix = 'config.'; private readonly _values = new Map(); private readonly _listener: IDisposable; diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts index 5345229bdc1..c3e684f944d 100644 --- a/src/vs/platform/instantiation/common/instantiationService.ts +++ b/src/vs/platform/instantiation/common/instantiationService.ts @@ -241,7 +241,7 @@ const enum TraceType { class Trace { - private static _None = new class extends Trace { + private static readonly _None = new class extends Trace { constructor() { super(-1, null); } stop() { } branch() { return this; } diff --git a/src/vs/platform/state/node/stateService.ts b/src/vs/platform/state/node/stateService.ts index 5f0a6d0cdc3..d5146ec25ac 100644 --- a/src/vs/platform/state/node/stateService.ts +++ b/src/vs/platform/state/node/stateService.ts @@ -127,7 +127,7 @@ export class StateService implements IStateService { _serviceBrand: undefined; - private static STATE_FILE = 'storage.json'; + private static readonly STATE_FILE = 'storage.json'; private fileStorage: FileStorage; diff --git a/src/vs/platform/storage/node/storageIpc.ts b/src/vs/platform/storage/node/storageIpc.ts index f74005b5ed4..b0a2b3752a5 100644 --- a/src/vs/platform/storage/node/storageIpc.ts +++ b/src/vs/platform/storage/node/storageIpc.ts @@ -29,7 +29,7 @@ interface ISerializableItemsChangeEvent { export class GlobalStorageDatabaseChannel extends Disposable implements IServerChannel { - private static STORAGE_CHANGE_DEBOUNCE_TIME = 100; + private static readonly STORAGE_CHANGE_DEBOUNCE_TIME = 100; private readonly _onDidChangeItems: Emitter = this._register(new Emitter()); readonly onDidChangeItems: Event = this._onDidChangeItems.event; diff --git a/src/vs/platform/storage/node/storageMainService.ts b/src/vs/platform/storage/node/storageMainService.ts index 70cdeef730d..81c9511a239 100644 --- a/src/vs/platform/storage/node/storageMainService.ts +++ b/src/vs/platform/storage/node/storageMainService.ts @@ -87,7 +87,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic _serviceBrand: undefined; - private static STORAGE_NAME = 'state.vscdb'; + private static readonly STORAGE_NAME = 'state.vscdb'; private readonly _onDidChangeStorage: Emitter = this._register(new Emitter()); readonly onDidChangeStorage: Event = this._onDidChangeStorage.event; diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index bd4bbd98a22..bdd7b454af1 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -21,8 +21,8 @@ export class NativeStorageService extends Disposable implements IStorageService _serviceBrand: undefined; - private static WORKSPACE_STORAGE_NAME = 'state.vscdb'; - private static WORKSPACE_META_NAME = 'workspace.json'; + private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb'; + private static readonly WORKSPACE_META_NAME = 'workspace.json'; private readonly _onDidChangeStorage: Emitter = this._register(new Emitter()); readonly onDidChangeStorage: Event = this._onDidChangeStorage.event; diff --git a/src/vs/platform/telemetry/common/telemetryService.ts b/src/vs/platform/telemetry/common/telemetryService.ts index 1e468a2018d..8e64e8e045a 100644 --- a/src/vs/platform/telemetry/common/telemetryService.ts +++ b/src/vs/platform/telemetry/common/telemetryService.ts @@ -24,8 +24,8 @@ export interface ITelemetryServiceConfig { export class TelemetryService implements ITelemetryService { - static IDLE_START_EVENT_NAME = 'UserIdleStart'; - static IDLE_STOP_EVENT_NAME = 'UserIdleStop'; + static readonly IDLE_START_EVENT_NAME = 'UserIdleStart'; + static readonly IDLE_STOP_EVENT_NAME = 'UserIdleStop'; _serviceBrand: undefined; diff --git a/src/vs/workbench/api/common/apiCommands.ts b/src/vs/workbench/api/common/apiCommands.ts index a1f752a77a0..01581c2c7c2 100644 --- a/src/vs/workbench/api/common/apiCommands.ts +++ b/src/vs/workbench/api/common/apiCommands.ts @@ -39,7 +39,7 @@ interface IOpenFolderAPICommandOptions { } export class OpenFolderAPICommand { - public static ID = 'vscode.openFolder'; + public static readonly ID = 'vscode.openFolder'; public static execute(executor: ICommandsExecutor, uri?: URI, forceNewWindow?: boolean): Promise; public static execute(executor: ICommandsExecutor, uri?: URI, options?: IOpenFolderAPICommandOptions): Promise; public static execute(executor: ICommandsExecutor, uri?: URI, arg: boolean | IOpenFolderAPICommandOptions = {}): Promise { @@ -73,7 +73,7 @@ interface INewWindowAPICommandOptions { } export class NewWindowAPICommand { - public static ID = 'vscode.newWindow'; + public static readonly ID = 'vscode.newWindow'; public static execute(executor: ICommandsExecutor, options?: INewWindowAPICommandOptions): Promise { const commandOptions: IOpenEmptyWindowOptions = { forceReuseWindow: options && options.reuseWindow, @@ -94,7 +94,7 @@ CommandsRegistry.registerCommand({ }); export class DiffAPICommand { - public static ID = 'vscode.diff'; + public static readonly ID = 'vscode.diff'; public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions): Promise { return executor.executeCommand('_workbench.diff', [ left, right, @@ -108,7 +108,7 @@ export class DiffAPICommand { CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute)); export class OpenAPICommand { - public static ID = 'vscode.open'; + public static readonly ID = 'vscode.open'; public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, label?: string): Promise { let options: ITextEditorOptions | undefined; let position: EditorViewColumn | undefined; @@ -138,7 +138,7 @@ CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function }); export class RemoveFromRecentlyOpenedAPICommand { - public static ID = 'vscode.removeFromRecentlyOpened'; + public static readonly ID = 'vscode.removeFromRecentlyOpened'; public static execute(executor: ICommandsExecutor, path: string | URI): Promise { if (typeof path === 'string') { path = path.match(/^[^:/?#]+:\/\//) ? URI.parse(path) : URI.file(path); @@ -151,7 +151,7 @@ export class RemoveFromRecentlyOpenedAPICommand { CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute)); export class OpenIssueReporter { - public static ID = 'vscode.openIssueReporter'; + public static readonly ID = 'vscode.openIssueReporter'; public static execute(executor: ICommandsExecutor, extensionId: string): Promise { return executor.executeCommand('workbench.action.openIssueReporter', [extensionId]); } @@ -185,7 +185,7 @@ CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function }); export class SetEditorLayoutAPICommand { - public static ID = 'vscode.setEditorLayout'; + public static readonly ID = 'vscode.setEditorLayout'; public static execute(executor: ICommandsExecutor, layout: EditorGroupLayout): Promise { return executor.executeCommand('layoutEditorGroups', layout); } diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index 95dc89564a1..24b55f765df 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -166,8 +166,8 @@ interface TreeNode extends IDisposable { class ExtHostTreeView extends Disposable { - private static LABEL_HANDLE_PREFIX = '0'; - private static ID_HANDLE_PREFIX = '1'; + private static readonly LABEL_HANDLE_PREFIX = '0'; + private static readonly ID_HANDLE_PREFIX = '1'; private readonly dataProvider: vscode.TreeDataProvider; diff --git a/src/vs/workbench/browser/actions/developerActions.ts b/src/vs/workbench/browser/actions/developerActions.ts index 1447d3f1b77..051b58f56ad 100644 --- a/src/vs/workbench/browser/actions/developerActions.ts +++ b/src/vs/workbench/browser/actions/developerActions.ts @@ -29,7 +29,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v class InspectContextKeysAction extends Action { static readonly ID = 'workbench.action.inspectContextKeys'; - static LABEL = nls.localize('inspect context keys', "Inspect Context Keys"); + static readonly LABEL = nls.localize('inspect context keys', "Inspect Context Keys"); constructor( id: string, @@ -91,7 +91,7 @@ class InspectContextKeysAction extends Action { class ToggleScreencastModeAction extends Action { static readonly ID = 'workbench.action.toggleScreencastMode'; - static LABEL = nls.localize('toggle screencast mode', "Toggle Screencast Mode"); + static readonly LABEL = nls.localize('toggle screencast mode', "Toggle Screencast Mode"); static disposable: IDisposable | undefined; @@ -195,7 +195,7 @@ class ToggleScreencastModeAction extends Action { class LogStorageAction extends Action { static readonly ID = 'workbench.action.logStorage'; - static LABEL = nls.localize({ key: 'logStorage', comment: ['A developer only action to log the contents of the storage for the current window.'] }, "Log Storage Database Contents"); + static readonly LABEL = nls.localize({ key: 'logStorage', comment: ['A developer only action to log the contents of the storage for the current window.'] }, "Log Storage Database Contents"); constructor( id: string, diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 05cd78e5a87..a10a3d58b9c 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -396,7 +396,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ export class ToggleMenuBarAction extends Action { static readonly ID = 'workbench.action.toggleMenuBar'; - static LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar"); + static readonly LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar"); private static readonly menuBarVisibilityKey = 'window.menuBarVisibility'; @@ -446,7 +446,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { export abstract class BaseResizeViewAction extends Action { - protected static RESIZE_INCREMENT = 6.5; // This is a media-size percentage + protected static readonly RESIZE_INCREMENT = 6.5; // This is a media-size percentage constructor( id: string, diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index cb60384a583..55a96615e36 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -193,7 +193,7 @@ class QuickOpenRecentAction extends BaseOpenRecentAction { class ToggleFullScreenAction extends Action { static readonly ID = 'workbench.action.toggleFullScreen'; - static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen"); + static readonly LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen"); constructor( id: string, @@ -211,7 +211,7 @@ class ToggleFullScreenAction extends Action { export class ReloadWindowAction extends Action { static readonly ID = 'workbench.action.reloadWindow'; - static LABEL = nls.localize('reloadWindow', "Reload Window"); + static readonly LABEL = nls.localize('reloadWindow', "Reload Window"); constructor( id: string, @@ -249,7 +249,7 @@ class ShowAboutDialogAction extends Action { export class NewWindowAction extends Action { static readonly ID = 'workbench.action.newWindow'; - static LABEL = nls.localize('newWindow', "New Window"); + static readonly LABEL = nls.localize('newWindow', "New Window"); constructor( id: string, diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index d0305aa9dde..b7d74392423 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -26,7 +26,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ export class OpenFileAction extends Action { static readonly ID = 'workbench.action.files.openFile'; - static LABEL = nls.localize('openFile', "Open File..."); + static readonly LABEL = nls.localize('openFile', "Open File..."); constructor( id: string, @@ -44,7 +44,7 @@ export class OpenFileAction extends Action { export class OpenFolderAction extends Action { static readonly ID = 'workbench.action.files.openFolder'; - static LABEL = nls.localize('openFolder', "Open Folder..."); + static readonly LABEL = nls.localize('openFolder', "Open Folder..."); constructor( id: string, @@ -62,7 +62,7 @@ export class OpenFolderAction extends Action { export class OpenFileFolderAction extends Action { static readonly ID = 'workbench.action.files.openFileFolder'; - static LABEL = nls.localize('openFileFolder', "Open..."); + static readonly LABEL = nls.localize('openFileFolder', "Open..."); constructor( id: string, @@ -80,7 +80,7 @@ export class OpenFileFolderAction extends Action { export class OpenWorkspaceAction extends Action { static readonly ID = 'workbench.action.openWorkspace'; - static LABEL = nls.localize('openWorkspaceAction', "Open Workspace..."); + static readonly LABEL = nls.localize('openWorkspaceAction', "Open Workspace..."); constructor( id: string, @@ -98,7 +98,7 @@ export class OpenWorkspaceAction extends Action { export class CloseWorkspaceAction extends Action { static readonly ID = 'workbench.action.closeFolder'; - static LABEL = nls.localize('closeWorkspace', "Close Workspace"); + static readonly LABEL = nls.localize('closeWorkspace', "Close Workspace"); constructor( id: string, @@ -150,7 +150,7 @@ export class OpenWorkspaceConfigFileAction extends Action { export class AddRootFolderAction extends Action { static readonly ID = 'workbench.action.addRootFolder'; - static LABEL = ADD_ROOT_FOLDER_LABEL; + static readonly LABEL = ADD_ROOT_FOLDER_LABEL; constructor( id: string, @@ -168,7 +168,7 @@ export class AddRootFolderAction extends Action { export class GlobalRemoveRootFolderAction extends Action { static readonly ID = 'workbench.action.removeRootFolder'; - static LABEL = nls.localize('globalRemoveFolderFromWorkspace', "Remove Folder from Workspace..."); + static readonly LABEL = nls.localize('globalRemoveFolderFromWorkspace', "Remove Folder from Workspace..."); constructor( id: string, diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index a4824f6c7b6..dfb216aa75e 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -226,7 +226,7 @@ class SwitchSideBarViewAction extends Action { export class PreviousSideBarViewAction extends SwitchSideBarViewAction { static readonly ID = 'workbench.action.previousSideBarView'; - static LABEL = nls.localize('previousSideBarView', 'Previous Side Bar View'); + static readonly LABEL = nls.localize('previousSideBarView', 'Previous Side Bar View'); constructor( id: string, @@ -245,7 +245,7 @@ export class PreviousSideBarViewAction extends SwitchSideBarViewAction { export class NextSideBarViewAction extends SwitchSideBarViewAction { static readonly ID = 'workbench.action.nextSideBarView'; - static LABEL = nls.localize('nextSideBarView', 'Next Side Bar View'); + static readonly LABEL = nls.localize('nextSideBarView', 'Next Side Bar View'); constructor( id: string, diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts index 96a35f5a192..df27f82a684 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts @@ -66,14 +66,14 @@ export abstract class BreadcrumbsConfig { // internal } - static IsEnabled = BreadcrumbsConfig._stub('breadcrumbs.enabled'); - static UseQuickPick = BreadcrumbsConfig._stub('breadcrumbs.useQuickPick'); - static FilePath = BreadcrumbsConfig._stub<'on' | 'off' | 'last'>('breadcrumbs.filePath'); - static SymbolPath = BreadcrumbsConfig._stub<'on' | 'off' | 'last'>('breadcrumbs.symbolPath'); - static SymbolSortOrder = BreadcrumbsConfig._stub<'position' | 'name' | 'type'>('breadcrumbs.symbolSortOrder'); - static Icons = BreadcrumbsConfig._stub('breadcrumbs.icons'); + static readonly IsEnabled = BreadcrumbsConfig._stub('breadcrumbs.enabled'); + static readonly UseQuickPick = BreadcrumbsConfig._stub('breadcrumbs.useQuickPick'); + static readonly FilePath = BreadcrumbsConfig._stub<'on' | 'off' | 'last'>('breadcrumbs.filePath'); + static readonly SymbolPath = BreadcrumbsConfig._stub<'on' | 'off' | 'last'>('breadcrumbs.symbolPath'); + static readonly SymbolSortOrder = BreadcrumbsConfig._stub<'position' | 'name' | 'type'>('breadcrumbs.symbolSortOrder'); + static readonly Icons = BreadcrumbsConfig._stub('breadcrumbs.icons'); - static FileExcludes = BreadcrumbsConfig._stub('files.exclude'); + static readonly FileExcludes = BreadcrumbsConfig._stub('files.exclude'); private static _stub(name: string): { bindTo(service: IConfigurationService): BreadcrumbsConfig } { return { diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 4594e365427..81ff34d2a50 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -130,15 +130,15 @@ export interface IBreadcrumbsControlOptions { export class BreadcrumbsControl { - static HEIGHT = 22; + static readonly HEIGHT = 22; static readonly Payload_Reveal = {}; static readonly Payload_RevealAside = {}; static readonly Payload_Pick = {}; - static CK_BreadcrumbsPossible = new RawContextKey('breadcrumbsPossible', false); - static CK_BreadcrumbsVisible = new RawContextKey('breadcrumbsVisible', false); - static CK_BreadcrumbsActive = new RawContextKey('breadcrumbsActive', false); + static readonly CK_BreadcrumbsPossible = new RawContextKey('breadcrumbsPossible', false); + static readonly CK_BreadcrumbsVisible = new RawContextKey('breadcrumbsVisible', false); + static readonly CK_BreadcrumbsActive = new RawContextKey('breadcrumbsActive', false); private readonly _ckBreadcrumbsPossible: IContextKey; private readonly _ckBreadcrumbsVisible: IContextKey; diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 3a11f85bbaf..94597ec5c07 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -24,7 +24,7 @@ interface IDropOperation { class DropOverlay extends Themable { - private static OVERLAY_ID = 'monaco-workbench-editor-drop-overlay'; + private static readonly OVERLAY_ID = 'monaco-workbench-editor-drop-overlay'; private container!: HTMLElement; private overlay!: HTMLElement; diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index a05135564ea..2bab7f303cf 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -26,7 +26,7 @@ import { assertAllDefined, assertIsDefined } from 'vs/base/common/types'; export class NotificationsCenter extends Themable { - private static MAX_DIMENSIONS = new Dimension(450, 400); + private static readonly MAX_DIMENSIONS = new Dimension(450, 400); private readonly _onDidChangeVisibility: Emitter = this._register(new Emitter()); readonly onDidChangeVisibility: Event = this._onDidChangeVisibility.event; diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index ae1d7024b7e..6a35cf36db8 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -41,8 +41,8 @@ enum ToastVisibility { export class NotificationsToasts extends Themable { - private static MAX_WIDTH = 450; - private static MAX_NOTIFICATIONS = 3; + private static readonly MAX_WIDTH = 450; + private static readonly MAX_NOTIFICATIONS = 3; private static PURGE_TIMEOUT: { [severity: number]: number } = (() => { const intervals = Object.create(null); diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index c8419eed7e7..30de9340067 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -21,7 +21,7 @@ import { ActivePanelContext, PanelPositionContext } from 'vs/workbench/common/pa export class ClosePanelAction extends Action { static readonly ID = 'workbench.action.closePanel'; - static LABEL = nls.localize('closePanel', "Close Panel"); + static readonly LABEL = nls.localize('closePanel', "Close Panel"); constructor( id: string, @@ -40,7 +40,7 @@ export class ClosePanelAction extends Action { export class TogglePanelAction extends Action { static readonly ID = 'workbench.action.togglePanel'; - static LABEL = nls.localize('togglePanel', "Toggle Panel"); + static readonly LABEL = nls.localize('togglePanel', "Toggle Panel"); constructor( id: string, @@ -209,7 +209,7 @@ export class SwitchPanelViewAction extends Action { export class PreviousPanelViewAction extends SwitchPanelViewAction { static readonly ID = 'workbench.action.previousPanelView'; - static LABEL = nls.localize('previousPanelView', 'Previous Panel View'); + static readonly LABEL = nls.localize('previousPanelView', 'Previous Panel View'); constructor( id: string, @@ -227,7 +227,7 @@ export class PreviousPanelViewAction extends SwitchPanelViewAction { export class NextPanelViewAction extends SwitchPanelViewAction { static readonly ID = 'workbench.action.nextPanelView'; - static LABEL = nls.localize('nextPanelView', 'Next Panel View'); + static readonly LABEL = nls.localize('nextPanelView', 'Next Panel View'); constructor( id: string, diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.ts b/src/vs/workbench/browser/parts/quickinput/quickInput.ts index 32c171d44a0..ddb957fee79 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInput.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.ts @@ -323,7 +323,7 @@ class QuickInput extends Disposable implements IQuickInput { class QuickPick extends QuickInput implements IQuickPick { - private static INPUT_BOX_ARIA_LABEL = localize('quickInputBox.ariaLabel', "Type to narrow down results."); + private static readonly INPUT_BOX_ARIA_LABEL = localize('quickInputBox.ariaLabel', "Type to narrow down results."); private _value = ''; private _placeholder: string; @@ -762,7 +762,7 @@ class QuickPick extends QuickInput implements IQuickPi class InputBox extends QuickInput implements IInputBox { - private static noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel"); + private static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel"); private _value = ''; private _valueSelection: Readonly<[number, number]>; diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index bd676c25d02..095b1c53211 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -81,7 +81,7 @@ export abstract class MenubarControl extends Disposable { protected menuUpdater: RunOnceScheduler; - protected static MAX_MENU_RECENT_ENTRIES = 10; + protected static readonly MAX_MENU_RECENT_ENTRIES = 10; constructor( protected readonly menuService: IMenuService, diff --git a/src/vs/workbench/browser/parts/views/panelViewlet.ts b/src/vs/workbench/browser/parts/views/panelViewlet.ts index fabd5818d2c..20b02e5ecd8 100644 --- a/src/vs/workbench/browser/parts/views/panelViewlet.ts +++ b/src/vs/workbench/browser/parts/views/panelViewlet.ts @@ -46,7 +46,7 @@ export interface IViewletPanelOptions extends IPanelOptions { export abstract class ViewletPanel extends Panel implements IView { - private static AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions'; + private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions'; private _onDidFocus = this._register(new Emitter()); readonly onDidFocus: Event = this._onDidFocus.event; diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index 6b0e55ec327..aa6aaf6890b 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -124,7 +124,7 @@ export class NotificationHandle implements INotificationHandle { export class NotificationsModel extends Disposable implements INotificationsModel { - private static NO_OP_NOTIFICATION = new NoOpNotification(); + private static readonly NO_OP_NOTIFICATION = new NoOpNotification(); private readonly _onDidNotificationChange: Emitter = this._register(new Emitter()); readonly onDidNotificationChange: Event = this._onDidNotificationChange.event; @@ -380,11 +380,11 @@ export interface INotificationMessage { export class NotificationViewItem extends Disposable implements INotificationViewItem { - private static MAX_MESSAGE_LENGTH = 1000; + private static readonly MAX_MESSAGE_LENGTH = 1000; // Example link: "Some message with [link text](http://link.href)." // RegEx: [, anything not ], ], (, http://|https://|command:, no whitespace) - private static LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi; + private static readonly LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi; private _expanded: boolean | undefined; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index f4f4ce7df80..c509716fc49 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -18,13 +18,13 @@ import { withNullAsUndefined } from 'vs/base/common/types'; export class ResourceContextKey extends Disposable implements IContextKey { - static Scheme = new RawContextKey('resourceScheme', undefined); - static Filename = new RawContextKey('resourceFilename', undefined); - static LangId = new RawContextKey('resourceLangId', undefined); - static Resource = new RawContextKey('resource', undefined); - static Extension = new RawContextKey('resourceExtname', undefined); - static HasResource = new RawContextKey('resourceSet', false); - static IsFileSystemResource = new RawContextKey('isFileSystemResource', false); + static readonly Scheme = new RawContextKey('resourceScheme', undefined); + static readonly Filename = new RawContextKey('resourceFilename', undefined); + static readonly LangId = new RawContextKey('resourceLangId', undefined); + static readonly Resource = new RawContextKey('resource', undefined); + static readonly Extension = new RawContextKey('resourceExtname', undefined); + static readonly HasResource = new RawContextKey('resourceSet', false); + static readonly IsFileSystemResource = new RawContextKey('isFileSystemResource', false); private readonly _resourceKey: IContextKey; private readonly _schemeKey: IContextKey; diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts index 1615bf30b86..d17090d01a3 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts @@ -26,13 +26,13 @@ const _ctxCallHierarchyVisible = new RawContextKey('callHierarchyVisibl class CallHierarchyController implements IEditorContribution { - static Id = 'callHierarchy'; + static readonly Id = 'callHierarchy'; static get(editor: ICodeEditor): CallHierarchyController { return editor.getContribution(CallHierarchyController.Id); } - private static _StorageDirection = 'callHierarchy/defaultDirection'; + private static readonly _StorageDirection = 'callHierarchy/defaultDirection'; private readonly _ctxHasProvider: IContextKey; private readonly _ctxIsVisible: IContextKey; diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts index dbe1dee06ad..274433e91cf 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts @@ -122,7 +122,7 @@ class CallRenderingTemplate { export class CallRenderer implements ITreeRenderer { - static id = 'CallRenderer'; + static readonly id = 'CallRenderer'; templateId: string = CallRenderer.id; diff --git a/src/vs/workbench/contrib/cli/node/cli.contribution.ts b/src/vs/workbench/contrib/cli/node/cli.contribution.ts index 7da113bc27f..985be2476f9 100644 --- a/src/vs/workbench/contrib/cli/node/cli.contribution.ts +++ b/src/vs/workbench/contrib/cli/node/cli.contribution.ts @@ -41,7 +41,7 @@ function isAvailable(): Promise { class InstallAction extends Action { static readonly ID = 'workbench.action.installCommandLine'; - static LABEL = nls.localize('install', "Install '{0}' command in PATH", product.applicationName); + static readonly LABEL = nls.localize('install', "Install '{0}' command in PATH", product.applicationName); constructor( id: string, @@ -122,7 +122,7 @@ class InstallAction extends Action { class UninstallAction extends Action { static readonly ID = 'workbench.action.uninstallCommandLine'; - static LABEL = nls.localize('uninstall', "Uninstall '{0}' command from PATH", product.applicationName); + static readonly LABEL = nls.localize('uninstall', "Uninstall '{0}' command from PATH", product.applicationName); constructor( id: string, diff --git a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts index ebf9955db2a..074e43dd377 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts @@ -17,7 +17,7 @@ import { EndOfLinePreference } from 'vs/editor/common/model'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; export class SelectionClipboard extends Disposable implements IEditorContribution { - private static SELECTION_LENGTH_LIMIT = 65536; + private static readonly SELECTION_LENGTH_LIMIT = 65536; private static readonly ID = 'editor.contrib.selectionClipboard'; constructor(editor: ICodeEditor, @IClipboardService clipboardService: IClipboardService) { diff --git a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts index 4cdcb6a6895..299a7271b2b 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts @@ -56,8 +56,8 @@ interface ICommentThreadTemplateData { } export class CommentsModelVirualDelegate implements IListVirtualDelegate { - private static RESOURCE_ID = 'resource-with-comments'; - private static COMMENT_ID = 'comment-node'; + private static readonly RESOURCE_ID = 'resource-with-comments'; + private static readonly COMMENT_ID = 'comment-node'; getHeight(element: any): number { diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 6f5605d3078..1440892a8f9 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -56,7 +56,7 @@ export abstract class AbstractDebugAction extends Action { export class ConfigureAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.configure'; - static LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); + static readonly LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json'); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @@ -156,7 +156,7 @@ export class RunAction extends StartAction { export class SelectAndStartAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.selectandstart'; - static LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); + static readonly LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @@ -173,7 +173,7 @@ export class SelectAndStartAction extends AbstractDebugAction { export class RemoveBreakpointAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.removeBreakpoint'; - static LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint"); + static readonly LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint"); constructor(id: string, label: string, @IDebugService private readonly debugService: IDebugService) { super(id, label, 'debug-action remove'); @@ -187,7 +187,7 @@ export class RemoveBreakpointAction extends Action { export class RemoveAllBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.removeAllBreakpoints'; - static LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints"); + static readonly LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action remove-all', debugService, keybindingService); @@ -206,7 +206,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { export class EnableAllBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.enableAllBreakpoints'; - static LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints"); + static readonly LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action enable-all-breakpoints', debugService, keybindingService); @@ -225,7 +225,7 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction { export class DisableAllBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.disableAllBreakpoints'; - static LABEL = nls.localize('disableAllBreakpoints', "Disable All Breakpoints"); + static readonly LABEL = nls.localize('disableAllBreakpoints', "Disable All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action disable-all-breakpoints', debugService, keybindingService); @@ -244,8 +244,8 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction { export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction'; - static ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints"); - static DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints"); + static readonly ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints"); + static readonly DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action breakpoints-activate', debugService, keybindingService); @@ -268,7 +268,7 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction { export class ReapplyBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction'; - static LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints"); + static readonly LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, '', debugService, keybindingService); @@ -288,7 +288,7 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction { export class AddFunctionBreakpointAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; - static LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); + static readonly LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action add-function-breakpoint', debugService, keybindingService); @@ -308,7 +308,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { export class AddWatchExpressionAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.addWatchExpression'; - static LABEL = nls.localize('addWatchExpression', "Add Expression"); + static readonly LABEL = nls.localize('addWatchExpression', "Add Expression"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action add-watch-expression', debugService, keybindingService); @@ -329,7 +329,7 @@ export class AddWatchExpressionAction extends AbstractDebugAction { export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions'; - static LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions"); + static readonly LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action remove-all', debugService, keybindingService); @@ -348,7 +348,7 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction { export class FocusSessionAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.focusProcess'; - static LABEL = nls.localize('focusSession', "Focus Session"); + static readonly LABEL = nls.localize('focusSession', "Focus Session"); constructor(id: string, label: string, @IDebugService debugService: IDebugService, @@ -371,7 +371,7 @@ export class FocusSessionAction extends AbstractDebugAction { export class CopyValueAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.copyValue'; - static LABEL = nls.localize('copyValue', "Copy Value"); + static readonly LABEL = nls.localize('copyValue', "Copy Value"); constructor( id: string, label: string, private value: any, private context: string, diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index 784694a387a..ea6cc952742 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -104,8 +104,8 @@ class LogPointAction extends EditorAction { export class RunToCursorAction extends EditorAction { - public static ID = 'editor.debug.action.runToCursor'; - public static LABEL = nls.localize('runToCursor', "Run to Cursor"); + public static readonly ID = 'editor.debug.action.runToCursor'; + public static readonly LABEL = nls.localize('runToCursor', "Run to Cursor"); constructor() { super({ diff --git a/src/vs/workbench/contrib/debug/browser/debugHover.ts b/src/vs/workbench/contrib/debug/browser/debugHover.ts index 812f5961f1b..13f6651d59b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugHover.ts +++ b/src/vs/workbench/contrib/debug/browser/debugHover.ts @@ -174,7 +174,7 @@ export class DebugHoverWidget implements IContentWidget { return this.doShow(pos, expression, focus); } - private static _HOVER_HIGHLIGHT_DECORATION_OPTIONS = ModelDecorationOptions.register({ + private static readonly _HOVER_HIGHLIGHT_DECORATION_OPTIONS = ModelDecorationOptions.register({ className: 'hoverHighlight' }); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 10681dbeda0..01d0a2e96d2 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -214,7 +214,7 @@ export class DebugViewlet extends ViewContainerViewlet { class ToggleReplAction extends TogglePanelAction { static readonly ID = 'debug.toggleRepl'; - static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console'); + static readonly LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console'); constructor(id: string, label: string, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, diff --git a/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts b/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts index da8e4c728e8..a72473eef46 100644 --- a/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts +++ b/src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts @@ -240,7 +240,7 @@ class RootTreeItem extends BaseTreeItem { class SessionTreeItem extends BaseTreeItem { - private static URL_REGEXP = /^(https?:\/\/[^/]+)(\/.*)$/; + private static readonly URL_REGEXP = /^(https?:\/\/[^/]+)(\/.*)$/; private _session: IDebugSession; private _initialized: boolean; diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index f15a1324cba..e19bb9c745a 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -982,7 +982,7 @@ class SelectReplActionViewItem extends FocusSessionActionViewItem { class SelectReplAction extends Action { static readonly ID = 'workbench.action.debug.selectRepl'; - static LABEL = nls.localize('selectRepl', "Select Debug Console"); + static readonly LABEL = nls.localize('selectRepl', "Select Debug Console"); constructor(id: string, label: string, @IDebugService private readonly debugService: IDebugService, @@ -1005,7 +1005,7 @@ class SelectReplAction extends Action { export class ClearReplAction extends Action { static readonly ID = 'workbench.debug.panel.action.clearReplAction'; - static LABEL = nls.localize('clearRepl', "Clear Console"); + static readonly LABEL = nls.localize('clearRepl', "Clear Console"); constructor(id: string, label: string, @IPanelService private readonly panelService: IPanelService diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index e93db64d746..489315df4b7 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -27,7 +27,7 @@ import { mixin } from 'vs/base/common/objects'; export class ExpressionContainer implements IExpressionContainer { - public static allValues = new Map(); + public static readonly allValues = new Map(); // Use chunks to support variable paging #9537 private static readonly BASE_CHUNK_SIZE = 100; @@ -172,7 +172,7 @@ export class ExpressionContainer implements IExpressionContainer { } export class Expression extends ExpressionContainer implements IExpression { - static DEFAULT_VALUE = nls.localize('notAvailable', "not available"); + static readonly DEFAULT_VALUE = nls.localize('notAvailable', "not available"); public available: boolean; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 94982ae98bb..3f53b905b71 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -143,8 +143,8 @@ export abstract class ExtensionAction extends Action implements IExtensionContai export class InstallAction extends ExtensionAction { - private static INSTALL_LABEL = localize('install', "Install"); - private static INSTALLING_LABEL = localize('installing', "Installing"); + private static readonly INSTALL_LABEL = localize('install', "Install"); + private static readonly INSTALLING_LABEL = localize('installing', "Installing"); private static readonly Class = 'extension-action prominent install'; private static readonly InstallingClass = 'extension-action install installing'; @@ -277,8 +277,8 @@ export class InstallAction extends ExtensionAction { export abstract class InstallInOtherServerAction extends ExtensionAction { - protected static INSTALL_LABEL = localize('install', "Install"); - protected static INSTALLING_LABEL = localize('installing', "Installing"); + protected static readonly INSTALL_LABEL = localize('install', "Install"); + protected static readonly INSTALLING_LABEL = localize('installing', "Installing"); private static readonly Class = 'extension-action prominent install'; private static readonly InstallingClass = 'extension-action install installing'; @@ -726,7 +726,7 @@ export class ManageExtensionAction extends ExtensionDropDownAction { export class InstallAnotherVersionAction extends ExtensionAction { static readonly ID = 'workbench.extensions.action.install.anotherVersion'; - static LABEL = localize('install another version', "Install Another Version..."); + static readonly LABEL = localize('install another version', "Install Another Version..."); constructor( @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -832,7 +832,7 @@ export class ExtensionSettingsAction extends ExtensionAction { export class EnableForWorkspaceAction extends ExtensionAction { static readonly ID = 'extensions.enableForWorkspace'; - static LABEL = localize('enableForWorkspaceAction', "Enable (Workspace)"); + static readonly LABEL = localize('enableForWorkspaceAction', "Enable (Workspace)"); constructor( @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -859,7 +859,7 @@ export class EnableForWorkspaceAction extends ExtensionAction { export class EnableGloballyAction extends ExtensionAction { static readonly ID = 'extensions.enableGlobally'; - static LABEL = localize('enableGloballyAction', "Enable"); + static readonly LABEL = localize('enableGloballyAction', "Enable"); constructor( @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -886,7 +886,7 @@ export class EnableGloballyAction extends ExtensionAction { export class DisableForWorkspaceAction extends ExtensionAction { static readonly ID = 'extensions.disableForWorkspace'; - static LABEL = localize('disableForWorkspaceAction', "Disable (Workspace)"); + static readonly LABEL = localize('disableForWorkspaceAction', "Disable (Workspace)"); constructor(readonly runningExtensions: IExtensionDescription[], @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, @@ -914,7 +914,7 @@ export class DisableForWorkspaceAction extends ExtensionAction { export class DisableGloballyAction extends ExtensionAction { static readonly ID = 'extensions.disableGlobally'; - static LABEL = localize('disableGloballyAction', "Disable"); + static readonly LABEL = localize('disableGloballyAction', "Disable"); constructor(readonly runningExtensions: IExtensionDescription[], @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -1010,7 +1010,7 @@ export class DisableDropDownAction extends ExtensionEditorDropDownAction { export class CheckForUpdatesAction extends Action { static readonly ID = 'workbench.extensions.action.checkForUpdates'; - static LABEL = localize('checkForUpdates', "Check for Extension Updates"); + static readonly LABEL = localize('checkForUpdates', "Check for Extension Updates"); constructor( id = CheckForUpdatesAction.ID, @@ -1082,7 +1082,7 @@ export class ToggleAutoUpdateAction extends Action { export class EnableAutoUpdateAction extends ToggleAutoUpdateAction { static readonly ID = 'workbench.extensions.action.enableAutoUpdate'; - static LABEL = localize('enableAutoUpdate', "Enable Auto Updating Extensions"); + static readonly LABEL = localize('enableAutoUpdate', "Enable Auto Updating Extensions"); constructor( id = EnableAutoUpdateAction.ID, @@ -1096,7 +1096,7 @@ export class EnableAutoUpdateAction extends ToggleAutoUpdateAction { export class DisableAutoUpdateAction extends ToggleAutoUpdateAction { static readonly ID = 'workbench.extensions.action.disableAutoUpdate'; - static LABEL = localize('disableAutoUpdate', "Disable Auto Updating Extensions"); + static readonly LABEL = localize('disableAutoUpdate', "Disable Auto Updating Extensions"); constructor( id = EnableAutoUpdateAction.ID, @@ -1110,7 +1110,7 @@ export class DisableAutoUpdateAction extends ToggleAutoUpdateAction { export class UpdateAllAction extends Action { static readonly ID = 'workbench.extensions.action.updateAllExtensions'; - static LABEL = localize('updateAll', "Update All Extensions"); + static readonly LABEL = localize('updateAll', "Update All Extensions"); constructor( id = UpdateAllAction.ID, @@ -1417,7 +1417,7 @@ export class InstallExtensionsAction extends OpenExtensionsViewletAction { export class ShowEnabledExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showEnabledExtensions'; - static LABEL = localize('showEnabledExtensions', "Show Enabled Extensions"); + static readonly LABEL = localize('showEnabledExtensions', "Show Enabled Extensions"); constructor( id: string, @@ -1440,7 +1440,7 @@ export class ShowEnabledExtensionsAction extends Action { export class ShowInstalledExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showInstalledExtensions'; - static LABEL = localize('showInstalledExtensions', "Show Installed Extensions"); + static readonly LABEL = localize('showInstalledExtensions', "Show Installed Extensions"); constructor( id: string, @@ -1463,7 +1463,7 @@ export class ShowInstalledExtensionsAction extends Action { export class ShowDisabledExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showDisabledExtensions'; - static LABEL = localize('showDisabledExtensions', "Show Disabled Extensions"); + static readonly LABEL = localize('showDisabledExtensions', "Show Disabled Extensions"); constructor( id: string, @@ -1486,7 +1486,7 @@ export class ShowDisabledExtensionsAction extends Action { export class ClearExtensionsInputAction extends Action { static readonly ID = 'workbench.extensions.action.clearExtensionsInput'; - static LABEL = localize('clearExtensionsInput', "Clear Extensions Input"); + static readonly LABEL = localize('clearExtensionsInput', "Clear Extensions Input"); constructor( id: string, @@ -1517,7 +1517,7 @@ export class ClearExtensionsInputAction extends Action { export class ShowBuiltInExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.listBuiltInExtensions'; - static LABEL = localize('showBuiltInExtensions', "Show Built-in Extensions"); + static readonly LABEL = localize('showBuiltInExtensions', "Show Built-in Extensions"); constructor( id: string, @@ -1540,7 +1540,7 @@ export class ShowBuiltInExtensionsAction extends Action { export class ShowOutdatedExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.listOutdatedExtensions'; - static LABEL = localize('showOutdatedExtensions', "Show Outdated Extensions"); + static readonly LABEL = localize('showOutdatedExtensions', "Show Outdated Extensions"); constructor( id: string, @@ -1563,7 +1563,7 @@ export class ShowOutdatedExtensionsAction extends Action { export class ShowPopularExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showPopularExtensions'; - static LABEL = localize('showPopularExtensions', "Show Popular Extensions"); + static readonly LABEL = localize('showPopularExtensions', "Show Popular Extensions"); constructor( id: string, @@ -1586,7 +1586,7 @@ export class ShowPopularExtensionsAction extends Action { export class ShowRecommendedExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showRecommendedExtensions'; - static LABEL = localize('showRecommendedExtensions', "Show Recommended Extensions"); + static readonly LABEL = localize('showRecommendedExtensions', "Show Recommended Extensions"); constructor( id: string, @@ -1609,7 +1609,7 @@ export class ShowRecommendedExtensionsAction extends Action { export class InstallWorkspaceRecommendedExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.installWorkspaceRecommendedExtensions'; - static LABEL = localize('installWorkspaceRecommendedExtensions', "Install All Workspace Recommended Extensions"); + static readonly LABEL = localize('installWorkspaceRecommendedExtensions', "Install All Workspace Recommended Extensions"); private _recommendations: IExtensionRecommendation[] = []; get recommendations(): IExtensionRecommendation[] { return this._recommendations; } @@ -1674,7 +1674,7 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action { export class InstallRecommendedExtensionAction extends Action { static readonly ID = 'workbench.extensions.action.installRecommendedExtension'; - static LABEL = localize('installRecommendedExtension', "Install Recommended Extension"); + static readonly LABEL = localize('installRecommendedExtension', "Install Recommended Extension"); private extensionId: string; @@ -1765,7 +1765,7 @@ export class UndoIgnoreExtensionRecommendationAction extends Action { export class ShowRecommendedKeymapExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showRecommendedKeymapExtensions'; - static SHORT_LABEL = localize('showRecommendedKeymapExtensionsShort', "Keymaps"); + static readonly SHORT_LABEL = localize('showRecommendedKeymapExtensionsShort', "Keymaps"); constructor( id: string, @@ -1788,7 +1788,7 @@ export class ShowRecommendedKeymapExtensionsAction extends Action { export class ShowLanguageExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showLanguageExtensions'; - static SHORT_LABEL = localize('showLanguageExtensionsShort', "Language Extensions"); + static readonly SHORT_LABEL = localize('showLanguageExtensionsShort', "Language Extensions"); constructor( id: string, @@ -1811,7 +1811,7 @@ export class ShowLanguageExtensionsAction extends Action { export class ShowAzureExtensionsAction extends Action { static readonly ID = 'workbench.extensions.action.showAzureExtensions'; - static SHORT_LABEL = localize('showAzureExtensionsShort', "Azure Extensions"); + static readonly SHORT_LABEL = localize('showAzureExtensionsShort', "Azure Extensions"); constructor( id: string, @@ -2153,7 +2153,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfigureRecommendedExtensionsAction { static readonly ID = 'workbench.extensions.action.configureWorkspaceRecommendedExtensions'; - static LABEL = localize('configureWorkspaceRecommendedExtensions', "Configure Recommended Extensions (Workspace)"); + static readonly LABEL = localize('configureWorkspaceRecommendedExtensions', "Configure Recommended Extensions (Workspace)"); constructor( @@ -2189,7 +2189,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfi export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends AbstractConfigureRecommendedExtensionsAction { static readonly ID = 'workbench.extensions.action.configureWorkspaceFolderRecommendedExtensions'; - static LABEL = localize('configureWorkspaceFolderRecommendedExtensions', "Configure Recommended Extensions (Workspace Folder)"); + static readonly LABEL = localize('configureWorkspaceFolderRecommendedExtensions', "Configure Recommended Extensions (Workspace Folder)"); constructor( @@ -2662,7 +2662,7 @@ export class SystemDisabledWarningAction extends ExtensionAction { export class DisableAllAction extends Action { static readonly ID = 'workbench.extensions.action.disableAll'; - static LABEL = localize('disableAll', "Disable All Installed Extensions"); + static readonly LABEL = localize('disableAll', "Disable All Installed Extensions"); constructor( @@ -2687,7 +2687,7 @@ export class DisableAllAction extends Action { export class DisableAllWorkspaceAction extends Action { static readonly ID = 'workbench.extensions.action.disableAllWorkspace'; - static LABEL = localize('disableAllWorkspace', "Disable All Installed Extensions for this Workspace"); + static readonly LABEL = localize('disableAllWorkspace', "Disable All Installed Extensions for this Workspace"); constructor( @@ -2714,7 +2714,7 @@ export class DisableAllWorkspaceAction extends Action { export class EnableAllAction extends Action { static readonly ID = 'workbench.extensions.action.enableAll'; - static LABEL = localize('enableAll', "Enable All Extensions"); + static readonly LABEL = localize('enableAll', "Enable All Extensions"); constructor( @@ -2739,7 +2739,7 @@ export class EnableAllAction extends Action { export class EnableAllWorkspaceAction extends Action { static readonly ID = 'workbench.extensions.action.enableAllWorkspace'; - static LABEL = localize('enableAllWorkspace', "Enable All Extensions for this Workspace"); + static readonly LABEL = localize('enableAllWorkspace', "Enable All Extensions for this Workspace"); constructor( @@ -2766,7 +2766,7 @@ export class EnableAllWorkspaceAction extends Action { export class InstallVSIXAction extends Action { static readonly ID = 'workbench.extensions.action.installVSIX'; - static LABEL = localize('installVSIX', "Install from VSIX..."); + static readonly LABEL = localize('installVSIX', "Install from VSIX..."); constructor( id = InstallVSIXAction.ID, @@ -2818,7 +2818,7 @@ export class InstallVSIXAction extends Action { export class ReinstallAction extends Action { static readonly ID = 'workbench.extensions.action.reinstall'; - static LABEL = localize('reinstall', "Reinstall Extension..."); + static readonly LABEL = localize('reinstall', "Reinstall Extension..."); constructor( id: string = ReinstallAction.ID, label: string = ReinstallAction.LABEL, @@ -2884,7 +2884,7 @@ export class ReinstallAction extends Action { export class InstallSpecificVersionOfExtensionAction extends Action { static readonly ID = 'workbench.extensions.action.install.specificVersion'; - static LABEL = localize('install previous version', "Install Specific Version of Extension..."); + static readonly LABEL = localize('install previous version', "Install Specific Version of Extension..."); constructor( id: string = InstallSpecificVersionOfExtensionAction.ID, label: string = InstallSpecificVersionOfExtensionAction.LABEL, diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts index b4185a6614f..871122fd967 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts @@ -14,7 +14,7 @@ import { Schemas } from 'vs/base/common/network'; export class OpenExtensionsFolderAction extends Action { static readonly ID = 'workbench.extensions.action.openExtensionsFolder'; - static LABEL = localize('openExtensionsFolder', "Open Extensions Folder"); + static readonly LABEL = localize('openExtensionsFolder', "Open Extensions Folder"); constructor( id: string, diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index ffe0daa5e1c..f3da8de29a1 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -459,7 +459,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { export class ShowRuntimeExtensionsAction extends Action { static readonly ID = 'workbench.action.showRuntimeExtensions'; - static LABEL = nls.localize('showRuntimeExtensions', "Show Running Extensions"); + static readonly LABEL = nls.localize('showRuntimeExtensions', "Show Running Extensions"); constructor( id: string, label: string, @@ -477,7 +477,7 @@ export class ShowRuntimeExtensionsAction extends Action { export class ReportExtensionIssueAction extends Action { private static readonly _id = 'workbench.extensions.action.reportExtensionIssue'; - private static _label = nls.localize('reportExtensionIssue', "Report Issue"); + private static readonly _label = nls.localize('reportExtensionIssue', "Report Issue"); private readonly _url: string; @@ -533,8 +533,8 @@ export class ReportExtensionIssueAction extends Action { export class DebugExtensionHostAction extends Action { static readonly ID = 'workbench.extensions.action.debugExtensionHost'; - static LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); - static CSS_CLASS = 'debug-extension-host'; + static readonly LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); + static readonly CSS_CLASS = 'debug-extension-host'; constructor( @IDebugService private readonly _debugService: IDebugService, @@ -572,7 +572,7 @@ export class DebugExtensionHostAction extends Action { export class StartExtensionHostProfileAction extends Action { static readonly ID = 'workbench.extensions.action.extensionHostProfile'; - static LABEL = nls.localize('extensionHostProfileStart', "Start Extension Host Profile"); + static readonly LABEL = nls.localize('extensionHostProfileStart', "Start Extension Host Profile"); constructor( id: string = StartExtensionHostProfileAction.ID, label: string = StartExtensionHostProfileAction.LABEL, @@ -589,7 +589,7 @@ export class StartExtensionHostProfileAction extends Action { export class StopExtensionHostProfileAction extends Action { static readonly ID = 'workbench.extensions.action.stopExtensionHostProfile'; - static LABEL = nls.localize('stopExtensionHostProfileStart', "Stop Extension Host Profile"); + static readonly LABEL = nls.localize('stopExtensionHostProfileStart', "Stop Extension Host Profile"); constructor( id: string = StartExtensionHostProfileAction.ID, label: string = StartExtensionHostProfileAction.LABEL, @@ -606,7 +606,7 @@ export class StopExtensionHostProfileAction extends Action { export class SaveExtensionHostProfileAction extends Action { - static LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); + static readonly LABEL = nls.localize('saveExtensionHostProfile', "Save Extension Host Profile"); static readonly ID = 'workbench.extensions.action.saveExtensionHostProfile'; constructor( diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index b3955354dc1..6e943f670f7 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -49,7 +49,7 @@ export class OpenEditorsView extends ViewletPanel { private static readonly DEFAULT_VISIBLE_OPEN_EDITORS = 9; static readonly ID = 'workbench.explorer.openEditorsView'; - static NAME = nls.localize({ key: 'openEditors', comment: ['Open is an adjective'] }, "Open Editors"); + static readonly NAME = nls.localize({ key: 'openEditors', comment: ['Open is an adjective'] }, "Open Editors"); private dirtyCountElement!: HTMLElement; private listRefreshScheduler: RunOnceScheduler; diff --git a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts index 4b726da442f..8142c039ed6 100644 --- a/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts +++ b/src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts @@ -33,7 +33,7 @@ type FormattingEditProvider = DocumentFormattingEditProvider | DocumentRangeForm class DefaultFormatter extends Disposable implements IWorkbenchContribution { - static configName = 'editor.defaultFormatter'; + static readonly configName = 'editor.defaultFormatter'; static extensionIds: (string | null)[] = []; static extensionDescriptions: string[] = []; diff --git a/src/vs/workbench/contrib/logs/common/logsActions.ts b/src/vs/workbench/contrib/logs/common/logsActions.ts index 34e9eed4475..625a8d7836a 100644 --- a/src/vs/workbench/contrib/logs/common/logsActions.ts +++ b/src/vs/workbench/contrib/logs/common/logsActions.ts @@ -15,8 +15,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic export class SetLogLevelAction extends Action { - static ID = 'workbench.action.setLogLevel'; - static LABEL = nls.localize('setLogLevel', "Set Log Level..."); + static readonly ID = 'workbench.action.setLogLevel'; + static readonly LABEL = nls.localize('setLogLevel', "Set Log Level..."); constructor(id: string, label: string, @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -60,8 +60,8 @@ export class SetLogLevelAction extends Action { export class OpenWindowSessionLogFileAction extends Action { - static ID = 'workbench.action.openSessionLogFile'; - static LABEL = nls.localize('openSessionLogFile', "Open Window Log File (Session)..."); + static readonly ID = 'workbench.action.openSessionLogFile'; + static readonly LABEL = nls.localize('openSessionLogFile', "Open Window Log File (Session)..."); constructor(id: string, label: string, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, diff --git a/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts b/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts index 547558b7deb..f2287b85265 100644 --- a/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts +++ b/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts @@ -12,8 +12,8 @@ import { IElectronService } from 'vs/platform/electron/node/electron'; export class OpenLogsFolderAction extends Action { - static ID = 'workbench.action.openLogsFolder'; - static LABEL = nls.localize('openLogsFolder', "Open Logs Folder"); + static readonly ID = 'workbench.action.openLogsFolder'; + static readonly LABEL = nls.localize('openLogsFolder', "Open Logs Folder"); constructor(id: string, label: string, @IEnvironmentService private readonly environmentService: IEnvironmentService, diff --git a/src/vs/workbench/contrib/output/browser/outputActions.ts b/src/vs/workbench/contrib/output/browser/outputActions.ts index 3760d018bf5..88e7d5b6e96 100644 --- a/src/vs/workbench/contrib/output/browser/outputActions.ts +++ b/src/vs/workbench/contrib/output/browser/outputActions.ts @@ -213,8 +213,8 @@ export class OpenLogOutputFile extends Action { export class ShowLogsOutputChannelAction extends Action { - static ID = 'workbench.action.showLogs'; - static LABEL = nls.localize('showLogs', "Show Logs..."); + static readonly ID = 'workbench.action.showLogs'; + static readonly LABEL = nls.localize('showLogs', "Show Logs..."); constructor(id: string, label: string, @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -243,8 +243,8 @@ interface IOutputChannelQuickPickItem extends IQuickPickItem { export class OpenOutputLogFileAction extends Action { - static ID = 'workbench.action.openLogFile'; - static LABEL = nls.localize('openLogFile', "Open Log File..."); + static readonly ID = 'workbench.action.openLogFile'; + static readonly LABEL = nls.localize('openLogFile', "Open Log File..."); constructor(id: string, label: string, @IQuickInputService private readonly quickInputService: IQuickInputService, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index ac4ff59a817..0ee5430c0e4 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -90,7 +90,7 @@ export class SettingsTreeNewExtensionsElement extends SettingsTreeElement { } export class SettingsTreeSettingElement extends SettingsTreeElement { - private static MAX_DESC_LINES = 20; + private static readonly MAX_DESC_LINES = 20; setting: ISetting; diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 14a04519113..bc4db1d2a9f 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -468,7 +468,7 @@ Registry.as(ViewletExtensions.Viewlets).registerViewlet(new Vie class OpenRemoteViewletAction extends ShowViewletAction { static readonly ID = VIEWLET_ID; - static LABEL = nls.localize('toggleRemoteViewlet', "Show Remote Explorer"); + static readonly LABEL = nls.localize('toggleRemoteViewlet', "Show Remote Explorer"); constructor(id: string, label: string, @IViewletService viewletService: IViewletService, @IEditorGroupsService editorGroupService: IEditorGroupsService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService) { super(id, label, VIEWLET_ID, viewletService, editorGroupService, layoutService); diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index 9566f4b1cba..d3e83e0d735 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -64,7 +64,7 @@ interface ResourceGroupTemplate { class ResourceGroupRenderer implements ICompressibleTreeRenderer { - static TEMPLATE_ID = 'resource group'; + static readonly TEMPLATE_ID = 'resource group'; get templateId(): string { return ResourceGroupRenderer.TEMPLATE_ID; } constructor( @@ -150,7 +150,7 @@ class MultipleSelectionActionRunner extends ActionRunner { class ResourceRenderer implements ICompressibleTreeRenderer, FuzzyScore, ResourceTemplate> { - static TEMPLATE_ID = 'resource'; + static readonly TEMPLATE_ID = 'resource'; get templateId(): string { return ResourceRenderer.TEMPLATE_ID; } constructor( diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 291d9386b1f..a8888407cb8 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -28,7 +28,7 @@ import { SCMService } from 'vs/workbench/contrib/scm/common/scmService'; class OpenSCMViewletAction extends ShowViewletAction { static readonly ID = VIEWLET_ID; - static LABEL = localize('toggleGitViewlet', "Show Git"); + static readonly LABEL = localize('toggleGitViewlet', "Show Git"); constructor(id: string, label: string, @IViewletService viewletService: IViewletService, @IEditorGroupsService editorGroupService: IEditorGroupsService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService) { super(id, label, VIEWLET_ID, viewletService, editorGroupService, layoutService); diff --git a/src/vs/workbench/contrib/search/browser/searchActions.ts b/src/vs/workbench/contrib/search/browser/searchActions.ts index 099312d3d98..c1dc5804ba3 100644 --- a/src/vs/workbench/contrib/search/browser/searchActions.ts +++ b/src/vs/workbench/contrib/search/browser/searchActions.ts @@ -494,7 +494,7 @@ export abstract class AbstractSearchAndReplaceAction extends Action { export class RemoveAction extends AbstractSearchAndReplaceAction { - static LABEL = nls.localize('RemoveAction.label', "Dismiss"); + static readonly LABEL = nls.localize('RemoveAction.label', "Dismiss"); constructor( private viewer: WorkbenchObjectTree, diff --git a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts index 20f06e31a9e..9522f3006b1 100644 --- a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts +++ b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts @@ -24,7 +24,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; export class TabCompletionController implements editorCommon.IEditorContribution { private static readonly ID = 'editor.tabCompletionController'; - static ContextKey = new RawContextKey('hasSnippetCompletions', undefined); + static readonly ContextKey = new RawContextKey('hasSnippetCompletions', undefined); public static get(editor: ICodeEditor): TabCompletionController { return editor.getContribution(TabCompletionController.ID); diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 0eefb3607a7..2f29f0d229b 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -113,7 +113,7 @@ export class TerminalTaskSystem implements ITaskSystem { public static TelemetryEventName: string = 'taskService'; - private static ProcessVarName = '__process__'; + private static readonly ProcessVarName = '__process__'; private static shellQuotes: IStringDictionary = { 'cmd': { diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 5026e50adad..8dc089688b4 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -27,7 +27,7 @@ import { IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/commo export class SelectColorThemeAction extends Action { static readonly ID = 'workbench.action.selectTheme'; - static LABEL = localize('selectTheme.label', "Color Theme"); + static readonly LABEL = localize('selectTheme.label', "Color Theme"); constructor( id: string, @@ -90,7 +90,7 @@ export class SelectColorThemeAction extends Action { class SelectIconThemeAction extends Action { static readonly ID = 'workbench.action.selectIconTheme'; - static LABEL = localize('selectIconTheme.label', "File Icon Theme"); + static readonly LABEL = localize('selectIconTheme.label', "File Icon Theme"); constructor( id: string, @@ -197,7 +197,7 @@ function toEntries(themes: Array, label?: string): class GenerateColorThemeAction extends Action { static readonly ID = 'workbench.action.generateColorTheme'; - static LABEL = localize('generateColorTheme.label', "Generate Color Theme From Current Settings"); + static readonly LABEL = localize('generateColorTheme.label', "Generate Color Theme From Current Settings"); constructor( id: string, @@ -288,4 +288,4 @@ MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { title: localize('themes.selectIconTheme.label', "File Icon Theme") }, order: 2 -}); \ No newline at end of file +}); diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index c93c32fede6..fd18b8d852b 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -103,7 +103,7 @@ export class ShowReleaseNotesAction extends AbstractShowReleaseNotesAction { export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesAction { static readonly ID = ShowCurrentReleaseNotesActionId; - static LABEL = nls.localize('showReleaseNotes', "Show Release Notes"); + static readonly LABEL = nls.localize('showReleaseNotes', "Show Release Notes"); constructor( id = ShowCurrentReleaseNotesAction.ID, diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditor.ts b/src/vs/workbench/contrib/webview/browser/webviewEditor.ts index 9f341bbb06c..cb620c83d9d 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditor.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditor.ts @@ -21,7 +21,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic export class WebviewEditor extends BaseEditor { - public static ID = 'WebviewEditor'; + public static readonly ID = 'WebviewEditor'; private readonly _scopedContextKeyService = this._register(new MutableDisposable()); private _findWidgetVisible: IContextKey; diff --git a/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts index 4a84a56125d..50398d48086 100644 --- a/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts @@ -20,7 +20,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution { - private static TELEMETRY_OPT_OUT_SHOWN = 'workbench.telemetryOptOutShown'; + private static readonly TELEMETRY_OPT_OUT_SHOWN = 'workbench.telemetryOptOutShown'; private privacyUrl: string | undefined; constructor( diff --git a/src/vs/workbench/electron-browser/actions/developerActions.ts b/src/vs/workbench/electron-browser/actions/developerActions.ts index d9b50a3f494..a33bd626c5a 100644 --- a/src/vs/workbench/electron-browser/actions/developerActions.ts +++ b/src/vs/workbench/electron-browser/actions/developerActions.ts @@ -11,7 +11,7 @@ import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedPr export class ToggleDevToolsAction extends Action { static readonly ID = 'workbench.action.toggleDevTools'; - static LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools"); + static readonly LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools"); constructor(id: string, label: string, @IElectronService private readonly electronService: IElectronService) { super(id, label); @@ -25,7 +25,7 @@ export class ToggleDevToolsAction extends Action { export class ToggleSharedProcessAction extends Action { static readonly ID = 'workbench.action.toggleSharedProcess'; - static LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process"); + static readonly LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process"); constructor(id: string, label: string, @ISharedProcessService private readonly sharedProcessService: ISharedProcessService) { super(id, label); diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-browser/actions/windowActions.ts index 2efe92ef881..9bc18a02043 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-browser/actions/windowActions.ts @@ -140,7 +140,7 @@ export class ZoomResetAction extends BaseZoomAction { export class ReloadWindowWithExtensionsDisabledAction extends Action { static readonly ID = 'workbench.action.reloadWindowWithExtensionsDisabled'; - static LABEL = nls.localize('reloadWindowWithExtensionsDisabled', "Reload With Extensions Disabled"); + static readonly LABEL = nls.localize('reloadWindowWithExtensionsDisabled', "Reload With Extensions Disabled"); constructor( id: string, @@ -217,7 +217,7 @@ export abstract class BaseSwitchWindow extends Action { export class SwitchWindow extends BaseSwitchWindow { static readonly ID = 'workbench.action.switchWindow'; - static LABEL = nls.localize('switchWindow', "Switch Window..."); + static readonly LABEL = nls.localize('switchWindow', "Switch Window..."); constructor( id: string, @@ -240,7 +240,7 @@ export class SwitchWindow extends BaseSwitchWindow { export class QuickSwitchWindow extends BaseSwitchWindow { static readonly ID = 'workbench.action.quickSwitchWindow'; - static LABEL = nls.localize('quickSwitchWindow', "Quick Switch Window..."); + static readonly LABEL = nls.localize('quickSwitchWindow', "Quick Switch Window..."); constructor( id: string, diff --git a/src/vs/workbench/electron-browser/actions/workspaceActions.ts b/src/vs/workbench/electron-browser/actions/workspaceActions.ts index ca7bcfab229..6647ac84756 100644 --- a/src/vs/workbench/electron-browser/actions/workspaceActions.ts +++ b/src/vs/workbench/electron-browser/actions/workspaceActions.ts @@ -14,7 +14,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ export class SaveWorkspaceAsAction extends Action { static readonly ID = 'workbench.action.saveWorkspaceAs'; - static LABEL = nls.localize('saveWorkspaceAsAction', "Save Workspace As..."); + static readonly LABEL = nls.localize('saveWorkspaceAsAction', "Save Workspace As..."); constructor( id: string, diff --git a/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts b/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts index 6962d84f471..623385c0a79 100644 --- a/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts +++ b/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts @@ -11,7 +11,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; export class NativeClipboardService implements IClipboardService { - private static FILE_FORMAT = 'code/file-list'; // Clipboard format for files + private static readonly FILE_FORMAT = 'code/file-list'; // Clipboard format for files _serviceBrand: undefined; diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index a4eedf25bfb..220b9d988e9 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -25,7 +25,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; export abstract class BaseConfigurationResolverService extends AbstractVariableResolverService { - static INPUT_OR_COMMAND_VARIABLES_PATTERN = /\${((input|command):(.*?))}/g; + static readonly INPUT_OR_COMMAND_VARIABLES_PATTERN = /\${((input|command):(.*?))}/g; constructor( envVariables: IProcessEnvironment, diff --git a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts index 32242293645..03f17d054c8 100644 --- a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts @@ -27,8 +27,8 @@ export interface IVariableResolveContext { export class AbstractVariableResolverService implements IConfigurationResolverService { - static VARIABLE_REGEXP = /\$\{(.*?)\}/g; - static VARIABLE_REGEXP_SINGLE = /\$\{(.*?)\}/; + static readonly VARIABLE_REGEXP = /\$\{(.*?)\}/g; + static readonly VARIABLE_REGEXP_SINGLE = /\$\{(.*?)\}/; _serviceBrand: undefined; diff --git a/src/vs/workbench/services/extensions/common/rpcProtocol.ts b/src/vs/workbench/services/extensions/common/rpcProtocol.ts index 7748ca5edbd..4f5f086a3f9 100644 --- a/src/vs/workbench/services/extensions/common/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/common/rpcProtocol.ts @@ -58,7 +58,7 @@ const noop = () => { }; export class RPCProtocol extends Disposable implements IRPCProtocol { - private static UNRESPONSIVE_TIME = 3 * 1000; // 3s + private static readonly UNRESPONSIVE_TIME = 3 * 1000; // 3s private readonly _onDidChangeResponsiveState: Emitter = this._register(new Emitter()); public readonly onDidChangeResponsiveState: Event = this._onDidChangeResponsiveState.event; diff --git a/src/vs/workbench/services/output/common/outputChannelModel.ts b/src/vs/workbench/services/output/common/outputChannelModel.ts index f3a8ec8ad94..2eade61f069 100644 --- a/src/vs/workbench/services/output/common/outputChannelModel.ts +++ b/src/vs/workbench/services/output/common/outputChannelModel.ts @@ -365,7 +365,7 @@ export class BufferredOutputChannel extends Disposable implements IOutputChannel class BufferedContent { - private static MAX_OUTPUT_LENGTH = 10000 /* Max. number of output lines to show in output */ * 100 /* Guestimated chars per line */; + private static readonly MAX_OUTPUT_LENGTH = 10000 /* Max. number of output lines to show in output */ * 100 /* Guestimated chars per line */; private data: string[] = []; private dataIds: number[] = []; diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts index 1b5f490f490..857096d4b0d 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts @@ -311,4 +311,4 @@ suite('Files - TextFileEditorModelManager', () => { manager.disposeModel((model as TextFileEditorModel)); manager.dispose(); }); -}); \ No newline at end of file +}); From 953d19337881fa3609f29f13181c3e1f20626c21 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 15:53:40 -0700 Subject: [PATCH 259/435] Removing zoomFactor logic for webviews Fixes #81783 This code was added to workaround bug in electron. It looks like it has since been fixed --- .../webview/electron-browser/webviewElement.ts | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index ab5c8d3df87..339c65c6bf4 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -567,24 +567,8 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } public layout(): void { - if (!this._webview || this._webview.style.width === '0px') { - return; - } - const contents = this._webview.getWebContents(); - if (!contents || contents.isDestroyed()) { - return; - } - const window = (contents as any).getOwnerBrowserWindow(); - if (!window || !window.webContents || window.webContents.isDestroyed()) { - return; - } - window.webContents.getZoomFactor((factor: number) => { - if (contents.isDestroyed()) { - return; - } + // noop - contents.setZoomFactor(factor); - }); } private readonly _hasFindResult = this._register(new Emitter()); From 4388300e89d1540700c3a4544ec605e9be97b63d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 16:25:24 -0700 Subject: [PATCH 260/435] Cache webview web contents Fixes #81780 --- .../electron-browser/webviewElement.ts | 104 ++++++++++-------- 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 339c65c6bf4..41940cec8e3 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -37,6 +37,43 @@ interface IKeydownEvent { repeat: boolean; } +class WebviewTagHandle extends Disposable { + + private _webContents: undefined | WebContents | 'destroyed'; + + public constructor( + public readonly webview: WebviewTag, + ) { + super(); + + this._register(addDisposableListener(this.webview, 'destroyed', () => { + this._webContents = 'destroyed'; + })); + + this._register(addDisposableListener(this.webview, 'did-start-loading', once(() => { + const contents = this.webContents; + if (contents) { + this._onFirstLoad.fire(contents); + } + }))); + } + + private readonly _onFirstLoad = this._register(new Emitter()); + public readonly onFirstLoad = this._onFirstLoad.event; + + public get webContents(): WebContents | undefined { + if (this._webContents === 'destroyed') { + return undefined; + } + if (this._webContents) { + return this._webContents; + } + this._webContents = this.webview.getWebContents(); + return this._webContents; + } + +} + type OnBeforeRequestDelegate = (details: OnBeforeRequestDetails) => Promise; type OnHeadersReceivedDelegate = (details: OnHeadersReceivedDetails) => { cancel: boolean; } | undefined; @@ -46,16 +83,11 @@ class WebviewSession extends Disposable { private readonly _onHeadersReceivedDelegates: Array = []; public constructor( - webview: WebviewTag, + webviewHandle: WebviewTagHandle, ) { super(); - this._register(addDisposableListener(webview, 'did-start-loading', once(() => { - const contents = webview.getWebContents(); - if (!contents) { - return; - } - + this._register(webviewHandle.onFirstLoad(contents => { contents.session.webRequest.onBeforeRequest(async (details, callback) => { for (const delegate of this._onBeforeRequestDelegates) { const result = await delegate(details); @@ -77,7 +109,7 @@ class WebviewSession extends Disposable { } callback({ cancel: false, responseHeaders: details.responseHeaders }); }); - }))); + })); } public onBeforeRequest(delegate: OnBeforeRequestDelegate) { @@ -91,26 +123,19 @@ class WebviewSession extends Disposable { class WebviewProtocolProvider extends Disposable { constructor( - webview: WebviewTag, + handle: WebviewTagHandle, private readonly _getExtensionLocation: () => URI | undefined, private readonly _getLocalResourceRoots: () => ReadonlyArray, private readonly _fileService: IFileService, ) { super(); - this._register(addDisposableListener(webview, 'did-start-loading', once(() => { - const contents = webview.getWebContents(); - if (contents) { - this.registerProtocols(contents); - } - }))); + this._register(handle.onFirstLoad(contents => { + this.registerProtocols(contents); + })); } private registerProtocols(contents: WebContents) { - if (contents.isDestroyed()) { - return; - } - registerFileProtocol(contents, WebviewResourceScheme, this._fileService, this._getExtensionLocation(), () => this._getLocalResourceRoots() ); @@ -142,25 +167,22 @@ class WebviewKeyboardHandler extends Disposable { private _ignoreMenuShortcut = false; constructor( - private readonly _webview: WebviewTag + private readonly _webviewHandle: WebviewTagHandle ) { super(); if (this.shouldToggleMenuShortcutsEnablement) { - this._register(addDisposableListener(this._webview, 'did-start-loading', () => { - const contents = this.getWebContents(); - if (contents) { - contents.on('before-input-event', (_event, input) => { - if (input.type === 'keyDown' && document.activeElement === this._webview) { - this._ignoreMenuShortcut = input.control || input.meta; - this.setIgnoreMenuShortcuts(this._ignoreMenuShortcut); - } - }); - } + this._register(_webviewHandle.onFirstLoad(contents => { + contents.on('before-input-event', (_event, input) => { + if (input.type === 'keyDown' && document.activeElement === this._webviewHandle.webview) { + this._ignoreMenuShortcut = input.control || input.meta; + this.setIgnoreMenuShortcuts(this._ignoreMenuShortcut); + } + }); })); } - this._register(addDisposableListener(this._webview, 'ipc-message', (event) => { + this._register(addDisposableListener(this._webviewHandle.webview, 'ipc-message', (event) => { switch (event.channel) { case 'did-keydown': // Electron: workaround for https://github.com/electron/electron/issues/14258 @@ -188,26 +210,18 @@ class WebviewKeyboardHandler extends Disposable { if (!this.shouldToggleMenuShortcutsEnablement) { return; } - const contents = this.getWebContents(); + const contents = this._webviewHandle.webContents; if (contents) { contents.setIgnoreMenuShortcuts(value); } } - private getWebContents(): WebContents | undefined { - const contents = this._webview.getWebContents(); - if (contents && !contents.isDestroyed()) { - return contents; - } - return undefined; - } - private handleKeydown(event: IKeydownEvent): void { // Create a fake KeyboardEvent from the data provided const emulatedKeyboardEvent = new KeyboardEvent('keydown', event); // Force override the target Object.defineProperty(emulatedKeyboardEvent, 'target', { - get: () => this._webview + get: () => this._webviewHandle.webview }); // And re-dispatch window.dispatchEvent(emulatedKeyboardEvent); @@ -281,10 +295,12 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, })); }); - const session = this._register(new WebviewSession(this._webview)); + const webviewAndContents = new WebviewTagHandle(this._webview); + + const session = this._register(new WebviewSession(webviewAndContents)); this._register(new WebviewProtocolProvider( - this._webview, + webviewAndContents, () => this.extension ? this.extension.location : undefined, () => (this.content.options.localResourceRoots || []), fileService)); @@ -296,7 +312,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, tunnelService, )); - this._register(new WebviewKeyboardHandler(this._webview)); + this._register(new WebviewKeyboardHandler(webviewAndContents)); this._register(addDisposableListener(this._webview, 'console-message', function (e: { level: number; message: string; line: number; sourceId: string; }) { console.log(`[Embedded Page] ${e.message}`); From 6fdd8d10dce66ee7981b15231634b39f21bfe98e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 16:38:17 -0700 Subject: [PATCH 261/435] Fixing strict init errors in webview code #78168 --- src/vs/workbench/api/common/extHostWebview.ts | 2 +- src/vs/workbench/contrib/webview/browser/webviewService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 763f79dc5f6..6526b1361d4 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -18,7 +18,7 @@ import { Disposable } from './extHostTypes'; type IconPath = URI | { light: URI, dark: URI }; export class ExtHostWebview implements vscode.Webview { - private _html: string; + private _html: string = ''; private _isDisposed: boolean = false; private _hasCalledAsWebviewUri = false; diff --git a/src/vs/workbench/contrib/webview/browser/webviewService.ts b/src/vs/workbench/contrib/webview/browser/webviewService.ts index 0b8c5b01c69..44610b046b8 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewService.ts @@ -18,7 +18,7 @@ export class WebviewService implements IWebviewService { constructor( @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { - this._instantiationService.createInstance(WebviewThemeDataProvider); + this._webviewThemeDataProvider = this._instantiationService.createInstance(WebviewThemeDataProvider); } createWebview( From 4a79a0ba4019e4f1bd636ac4d11396aead31bff6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 7 Oct 2019 16:41:39 -0700 Subject: [PATCH 262/435] Fixing a few more strict init errors in panelViewlet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #78168Ï --- .../browser/parts/views/panelViewlet.ts | 48 ++++++++++++------- .../contrib/debug/browser/variablesView.ts | 6 ++- .../debug/browser/watchExpressionsView.ts | 10 ++-- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/panelViewlet.ts b/src/vs/workbench/browser/parts/views/panelViewlet.ts index 20b02e5ecd8..7a6e3e450ce 100644 --- a/src/vs/workbench/browser/parts/views/panelViewlet.ts +++ b/src/vs/workbench/browser/parts/views/panelViewlet.ts @@ -29,6 +29,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IView, FocusedViewContext } from 'vs/workbench/common/views'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { assertIsDefined } from 'vs/base/common/types'; export interface IPanelColors extends IColorMapping { dropBackground?: ColorIdentifier; @@ -67,11 +68,11 @@ export abstract class ViewletPanel extends Panel implements IView { readonly title: string; protected actionRunner?: IActionRunner; - protected toolbar: ToolBar; + protected toolbar?: ToolBar; private readonly showActionsAlways: boolean = false; - private headerContainer: HTMLElement; - private titleContainer: HTMLElement; - protected twistiesContainer: HTMLElement; + private headerContainer?: HTMLElement; + private titleContainer?: HTMLElement; + protected twistiesContainer?: HTMLElement; constructor( options: IViewletPanelOptions, @@ -165,7 +166,9 @@ export abstract class ViewletPanel extends Panel implements IView { } protected updateTitle(title: string): void { - this.titleContainer.textContent = title; + if (this.titleContainer) { + this.titleContainer.textContent = title; + } this._onDidChangeTitleArea.fire(); } @@ -177,11 +180,16 @@ export abstract class ViewletPanel extends Panel implements IView { } private setActions(): void { - this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions()))(); - this.toolbar.context = this.getActionsContext(); + if (this.toolbar) { + this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions()))(); + this.toolbar.context = this.getActionsContext(); + } } private updateActionsVisibility(): void { + if (!this.headerContainer) { + return; + } const shouldAlwaysShowActions = this.configurationService.getValue('workbench.view.alwaysShowHeaderActions'); toggleClass(this.headerContainer, 'actions-always-visible', shouldAlwaysShowActions); } @@ -229,10 +237,10 @@ export class PanelViewlet extends Viewlet { private lastFocusedPanel: ViewletPanel | undefined; private panelItems: IViewletPanelItem[] = []; - private panelview: PanelView; + private panelview?: PanelView; get onDidSashChange(): Event { - return this.panelview.onDidSashChange; + return assertIsDefined(this.panelview).onDidSashChange; } protected get panels(): ViewletPanel[] { @@ -274,7 +282,7 @@ export class PanelViewlet extends Viewlet { event.stopPropagation(); event.preventDefault(); - let anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; + let anchor: { x: number, y: number; } = { x: event.posx, y: event.posy }; this.contextMenuService.showContextMenu({ getAnchor: () => anchor, getActions: () => this.getContextMenuActions() @@ -332,7 +340,9 @@ export class PanelViewlet extends Viewlet { } layout(dimension: Dimension): void { - this.panelview.layout(dimension.height, dimension.width); + if (this.panelview) { + this.panelview.layout(dimension.height, dimension.width); + } } getOptimalWidth(): number { @@ -342,7 +352,7 @@ export class PanelViewlet extends Viewlet { return Math.max(...sizes); } - addPanels(panels: { panel: ViewletPanel, size: number, index?: number }[]): void { + addPanels(panels: { panel: ViewletPanel, size: number, index?: number; }[]): void { const wasSingleView = this.isSingleView(); for (const { panel, size, index } of panels) { @@ -378,7 +388,7 @@ export class PanelViewlet extends Viewlet { const panelItem: IViewletPanelItem = { panel, disposable }; this.panelItems.splice(index, 0, panelItem); - this.panelview.addPanel(panel, size, index); + assertIsDefined(this.panelview).addPanel(panel, size, index); } removePanels(panels: ViewletPanel[]): void { @@ -403,7 +413,7 @@ export class PanelViewlet extends Viewlet { this.lastFocusedPanel = undefined; } - this.panelview.removePanel(panel); + assertIsDefined(this.panelview).removePanel(panel); const [panelItem] = this.panelItems.splice(index, 1); panelItem.disposable.dispose(); @@ -424,15 +434,15 @@ export class PanelViewlet extends Viewlet { const [panelItem] = this.panelItems.splice(fromIndex, 1); this.panelItems.splice(toIndex, 0, panelItem); - this.panelview.movePanel(from, to); + assertIsDefined(this.panelview).movePanel(from, to); } resizePanel(panel: ViewletPanel, size: number): void { - this.panelview.resizePanel(panel, size); + assertIsDefined(this.panelview).resizePanel(panel, size); } getPanelSize(panel: ViewletPanel): number { - return this.panelview.getPanelSize(panel); + return assertIsDefined(this.panelview).getPanelSize(panel); } protected updateViewHeaders(): void { @@ -451,6 +461,8 @@ export class PanelViewlet extends Viewlet { dispose(): void { super.dispose(); this.panelItems.forEach(i => i.disposable.dispose()); - this.panelview.dispose(); + if (this.panelview) { + this.panelview.dispose(); + } } } diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index 56483de1cb2..f7fb8d0f9eb 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -100,8 +100,10 @@ export class VariablesView extends ViewletPanel { CONTEXT_VARIABLES_FOCUSED.bindTo(this.tree.contextKeyService); - const collapseAction = new CollapseAction(this.tree, true, 'explorer-action collapse-explorer'); - this.toolbar.setActions([collapseAction])(); + if (this.toolbar) { + const collapseAction = new CollapseAction(this.tree, true, 'explorer-action collapse-explorer'); + this.toolbar.setActions([collapseAction])(); + } this.tree.updateChildren(); this._register(this.debugService.getViewModel().onDidFocusStackFrame(sf => { diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index b48786ed88b..db51214714d 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -74,10 +74,12 @@ export class WatchExpressionsView extends ViewletPanel { this.tree.setInput(this.debugService).then(undefined, onUnexpectedError); CONTEXT_WATCH_EXPRESSIONS_FOCUSED.bindTo(this.tree.contextKeyService); - const addWatchExpressionAction = new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService); - const collapseAction = new CollapseAction(this.tree, true, 'explorer-action collapse-explorer'); - const removeAllWatchExpressionsAction = new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService); - this.toolbar.setActions([addWatchExpressionAction, collapseAction, removeAllWatchExpressionsAction])(); + if (this.toolbar) { + const addWatchExpressionAction = new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService); + const collapseAction = new CollapseAction(this.tree, true, 'explorer-action collapse-explorer'); + const removeAllWatchExpressionsAction = new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService); + this.toolbar.setActions([addWatchExpressionAction, collapseAction, removeAllWatchExpressionsAction])(); + } this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); this._register(this.tree.onMouseDblClick(e => this.onMouseDblClick(e))); From 10545c3a925863c4c0a8c6c6e834518ddbae1343 Mon Sep 17 00:00:00 2001 From: IllusionMH Date: Tue, 8 Oct 2019 03:05:23 +0300 Subject: [PATCH 263/435] Fallback to PCRE2 if match whole word used with regexp --- .../services/search/node/ripgrepTextSearchEngine.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index 554762af58b..d89964a436b 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -425,13 +425,14 @@ function getRgArgs(query: TextSearchQuery, options: TextSearchOptions): string[] args.push('--pcre2'); } - if (query.isRegExp) { - query.pattern = unicodeEscapesToPCRE2(query.pattern); - } - // Allow $ to match /r/n args.push('--crlf'); + if (query.isRegExp) { + query.pattern = unicodeEscapesToPCRE2(query.pattern); + args.push('--auto-hybrid-regex'); + } + let searchPatternAfterDoubleDashes: Maybe; if (query.isWordMatch) { const regexp = createRegExp(query.pattern, !!query.isRegExp, { wholeWord: query.isWordMatch }); @@ -441,7 +442,6 @@ function getRgArgs(query: TextSearchQuery, options: TextSearchOptions): string[] let fixedRegexpQuery = fixRegexNewline(query.pattern); fixedRegexpQuery = fixNewline(fixedRegexpQuery); args.push('--regexp', fixedRegexpQuery); - args.push('--auto-hybrid-regex'); } else { searchPatternAfterDoubleDashes = query.pattern; args.push('--fixed-strings'); From 79722879ba315bc60d7a35a72f3cb2a57bec2815 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 09:53:53 +0200 Subject: [PATCH 264/435] debt - less null in workbench --- .../browser/actions/navigationActions.ts | 4 +- .../workbench/browser/parts/compositePart.ts | 4 +- .../browser/parts/sidebar/sidebarPart.ts | 13 ++-- src/vs/workbench/browser/viewlet.ts | 4 +- src/vs/workbench/browser/web.main.ts | 4 +- src/vs/workbench/common/notifications.ts | 16 ++-- src/vs/workbench/common/viewlet.ts | 2 +- .../contrib/files/browser/fileActions.ts | 74 +++++++++---------- .../services/panel/common/panelService.ts | 2 +- .../progress/browser/progressService.ts | 2 +- .../services/viewlet/browser/viewlet.ts | 8 +- .../workbench/test/workbenchTestServices.ts | 6 +- 12 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/vs/workbench/browser/actions/navigationActions.ts b/src/vs/workbench/browser/actions/navigationActions.ts index aa46d31242f..fae9742c7bf 100644 --- a/src/vs/workbench/browser/actions/navigationActions.ts +++ b/src/vs/workbench/browser/actions/navigationActions.ts @@ -94,8 +94,8 @@ abstract class BaseNavigationAction extends Action { } const activeViewletId = activeViewlet.getId(); - const value = await this.viewletService.openViewlet(activeViewletId, true); - return value === null ? false : value; + const viewlet = await this.viewletService.openViewlet(activeViewletId, true); + return !!viewlet; } protected navigateAcrossEditorGroup(direction: GroupDirection): boolean { diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index c71cbac2538..b181734523b 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -445,10 +445,10 @@ export abstract class CompositePart extends Part { return contentContainer; } - getProgressIndicator(id: string): IProgressIndicator | null { + getProgressIndicator(id: string): IProgressIndicator | undefined { const compositeItem = this.instantiatedCompositeItems.get(id); - return compositeItem ? compositeItem.progress : null; + return compositeItem ? compositeItem.progress : undefined; } protected getActions(): ReadonlyArray { diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index f57dcf23174..9600cb74a4f 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -59,7 +59,6 @@ export class SidebarPart extends CompositePart implements IViewletServi } const width = viewlet.getOptimalWidth(); - if (typeof width !== 'number') { return; } @@ -199,7 +198,7 @@ export class SidebarPart extends CompositePart implements IViewletServi // Viewlet service - getActiveViewlet(): IViewlet | null { + getActiveViewlet(): IViewlet | undefined { return this.getActiveComposite(); } @@ -211,7 +210,7 @@ export class SidebarPart extends CompositePart implements IViewletServi this.hideActiveComposite(); } - async openViewlet(id: string | undefined, focus?: boolean): Promise { + async openViewlet(id: string | undefined, focus?: boolean): Promise { if (typeof id === 'string' && this.getViewlet(id)) { return this.doOpenViewlet(id, focus); } @@ -222,7 +221,7 @@ export class SidebarPart extends CompositePart implements IViewletServi return this.doOpenViewlet(id, focus); } - return null; + return undefined; } getViewlets(): ViewletDescriptor[] { @@ -247,9 +246,9 @@ export class SidebarPart extends CompositePart implements IViewletServi return this.getViewlets().filter(viewlet => viewlet.id === id)[0]; } - private doOpenViewlet(id: string, focus?: boolean): Viewlet | null { + private doOpenViewlet(id: string, focus?: boolean): Viewlet | undefined { if (this.blockOpeningViewlet) { - return null; // Workaround against a potential race condition + return undefined; // Workaround against a potential race condition } // First check if sidebar is hidden and show if so @@ -318,7 +317,7 @@ class FocusSideBarAction extends Action { } // Focus into active viewlet - let viewlet = this.viewletService.getActiveViewlet(); + const viewlet = this.viewletService.getActiveViewlet(); if (viewlet) { viewlet.focus(); } diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 35b8233db03..6ddf85eb74b 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -35,8 +35,8 @@ export abstract class Viewlet extends Composite implements IViewlet { super(id, telemetryService, themeService, storageService); } - getOptimalWidth(): number | null { - return null; + getOptimalWidth(): number | undefined { + return undefined; } getContextMenuActions(): IAction[] { diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index e5e351cf7d8..51194632b7d 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -303,7 +303,7 @@ class BrowserMain extends Disposable { return { id: 'empty-window' }; } - private getRemoteUserDataUri(): URI | null { + private getRemoteUserDataUri(): URI | undefined { const element = document.getElementById('vscode-remote-user-data-uri'); if (element) { const remoteUserDataPath = element.getAttribute('data-settings'); @@ -312,7 +312,7 @@ class BrowserMain extends Disposable { } } - return null; + return undefined; } } diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index aa6aaf6890b..f0a492bad2c 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -173,10 +173,10 @@ export class NotificationsModel extends Disposable implements INotificationsMode return find(this._notifications, notification => notification.equals(item)); } - private createViewItem(notification: INotification): INotificationViewItem | null { + private createViewItem(notification: INotification): INotificationViewItem | undefined { const item = NotificationViewItem.create(notification); if (!item) { - return null; + return undefined; } // Item Events @@ -400,9 +400,9 @@ export class NotificationViewItem extends Disposable implements INotificationVie private readonly _onDidLabelChange: Emitter = this._register(new Emitter()); readonly onDidLabelChange: Event = this._onDidLabelChange.event; - static create(notification: INotification): INotificationViewItem | null { + static create(notification: INotification): INotificationViewItem | undefined { if (!notification || !notification.message || isPromiseCanceledError(notification.message)) { - return null; // we need a message to show + return undefined; // we need a message to show } let severity: Severity; @@ -414,7 +414,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie const message = NotificationViewItem.parseNotificationMessage(notification.message); if (!message) { - return null; // we need a message to show + return undefined; // we need a message to show } let actions: INotificationActions | undefined; @@ -675,9 +675,9 @@ export class ChoiceAction extends Action { class StatusMessageViewItem { - static create(notification: NotificationMessage, options?: IStatusMessageOptions): IStatusMessageViewItem | null { + static create(notification: NotificationMessage, options?: IStatusMessageOptions): IStatusMessageViewItem | undefined { if (!notification || isPromiseCanceledError(notification)) { - return null; // we need a message to show + return undefined; // we need a message to show } let message: string | undefined; @@ -688,7 +688,7 @@ class StatusMessageViewItem { } if (!message) { - return null; // we need a message to show + return undefined; // we need a message to show } return { message, options }; diff --git a/src/vs/workbench/common/viewlet.ts b/src/vs/workbench/common/viewlet.ts index ddb8340130c..01fafea5968 100644 --- a/src/vs/workbench/common/viewlet.ts +++ b/src/vs/workbench/common/viewlet.ts @@ -15,5 +15,5 @@ export interface IViewlet extends IComposite { /** * Returns the minimal width needed to avoid any content horizontal truncation */ - getOptimalWidth(): number | null; + getOptimalWidth(): number | undefined; } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 3cdcb6c65e5..3768bc96d17 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -125,8 +125,8 @@ export class NewFolderAction extends Action { /* Create new file from anywhere: Open untitled */ export class GlobalNewUntitledFileAction extends Action { - public static readonly ID = 'workbench.action.files.newUntitledFile'; - public static readonly LABEL = nls.localize('newUntitledFile', "New Untitled File"); + static readonly ID = 'workbench.action.files.newUntitledFile'; + static readonly LABEL = nls.localize('newUntitledFile', "New Untitled File"); constructor( id: string, @@ -136,7 +136,7 @@ export class GlobalNewUntitledFileAction extends Action { super(id, label); } - public run(): Promise { + run(): Promise { return this.editorService.openEditor({ options: { pinned: true } }); // untitled are always pinned } } @@ -440,8 +440,8 @@ export function incrementFileName(name: string, isFolder: boolean, incrementalNa // Global Compare with export class GlobalCompareResourcesAction extends Action { - public static readonly ID = 'workbench.files.action.compareFileWith'; - public static readonly LABEL = nls.localize('globalCompareFile', "Compare Active File With..."); + static readonly ID = 'workbench.files.action.compareFileWith'; + static readonly LABEL = nls.localize('globalCompareFile', "Compare Active File With..."); constructor( id: string, @@ -453,7 +453,7 @@ export class GlobalCompareResourcesAction extends Action { super(id, label); } - public run(): Promise { + run(): Promise { const activeInput = this.editorService.activeEditor; const activeResource = activeInput ? activeInput.getResource() : undefined; if (activeResource) { @@ -491,8 +491,8 @@ export class GlobalCompareResourcesAction extends Action { } export class ToggleAutoSaveAction extends Action { - public static readonly ID = 'workbench.action.toggleAutoSave'; - public static readonly LABEL = nls.localize('toggleAutoSave', "Toggle Auto Save"); + static readonly ID = 'workbench.action.toggleAutoSave'; + static readonly LABEL = nls.localize('toggleAutoSave', "Toggle Auto Save"); constructor( id: string, @@ -502,7 +502,7 @@ export class ToggleAutoSaveAction extends Action { super(id, label); } - public run(): Promise { + run(): Promise { const setting = this.configurationService.inspect('files.autoSave'); let userAutoSaveConfig = setting.user; if (types.isUndefinedOrNull(userAutoSaveConfig)) { @@ -562,7 +562,7 @@ export abstract class BaseSaveAllAction extends Action { } } - public run(context?: any): Promise { + run(context?: any): Promise { return this.doRun(context).then(() => true, error => { onError(this.notificationService, error); return false; @@ -572,10 +572,10 @@ export abstract class BaseSaveAllAction extends Action { export class SaveAllAction extends BaseSaveAllAction { - public static readonly ID = 'workbench.action.files.saveAll'; - public static readonly LABEL = SAVE_ALL_LABEL; + static readonly ID = 'workbench.action.files.saveAll'; + static readonly LABEL = SAVE_ALL_LABEL; - public get class(): string { + get class(): string { return 'explorer-action codicon-save-all'; } @@ -590,10 +590,10 @@ export class SaveAllAction extends BaseSaveAllAction { export class SaveAllInGroupAction extends BaseSaveAllAction { - public static readonly ID = 'workbench.files.action.saveAllInGroup'; - public static readonly LABEL = nls.localize('saveAllInGroup', "Save All in Group"); + static readonly ID = 'workbench.files.action.saveAllInGroup'; + static readonly LABEL = nls.localize('saveAllInGroup', "Save All in Group"); - public get class(): string { + get class(): string { return 'explorer-action codicon-save-all'; } @@ -608,22 +608,22 @@ export class SaveAllInGroupAction extends BaseSaveAllAction { export class CloseGroupAction extends Action { - public static readonly ID = 'workbench.files.action.closeGroup'; - public static readonly LABEL = nls.localize('closeGroup', "Close Group"); + static readonly ID = 'workbench.files.action.closeGroup'; + static readonly LABEL = nls.localize('closeGroup', "Close Group"); constructor(id: string, label: string, @ICommandService private readonly commandService: ICommandService) { super(id, label, 'codicon-close-all'); } - public run(context?: any): Promise { + run(context?: any): Promise { return this.commandService.executeCommand(CLOSE_EDITORS_AND_GROUP_COMMAND_ID, {}, context); } } export class FocusFilesExplorer extends Action { - public static readonly ID = 'workbench.files.action.focusFilesExplorer'; - public static readonly LABEL = nls.localize('focusFilesExplorer', "Focus on Files Explorer"); + static readonly ID = 'workbench.files.action.focusFilesExplorer'; + static readonly LABEL = nls.localize('focusFilesExplorer', "Focus on Files Explorer"); constructor( id: string, @@ -633,15 +633,15 @@ export class FocusFilesExplorer extends Action { super(id, label); } - public run(): Promise { + run(): Promise { return this.viewletService.openViewlet(VIEWLET_ID, true); } } export class ShowActiveFileInExplorer extends Action { - public static readonly ID = 'workbench.files.action.showActiveFileInExplorer'; - public static readonly LABEL = nls.localize('showInExplorer', "Reveal Active File in Side Bar"); + static readonly ID = 'workbench.files.action.showActiveFileInExplorer'; + static readonly LABEL = nls.localize('showInExplorer', "Reveal Active File in Side Bar"); constructor( id: string, @@ -653,7 +653,7 @@ export class ShowActiveFileInExplorer extends Action { super(id, label); } - public run(): Promise { + run(): Promise { const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }); if (resource) { this.commandService.executeCommand(REVEAL_IN_EXPLORER_COMMAND_ID, resource); @@ -667,8 +667,8 @@ export class ShowActiveFileInExplorer extends Action { export class CollapseExplorerView extends Action { - public static readonly ID = 'workbench.files.action.collapseExplorerFolders'; - public static readonly LABEL = nls.localize('collapseExplorerFolders', "Collapse Folders in Explorer"); + static readonly ID = 'workbench.files.action.collapseExplorerFolders'; + static readonly LABEL = nls.localize('collapseExplorerFolders', "Collapse Folders in Explorer"); constructor(id: string, label: string, @@ -694,8 +694,8 @@ export class CollapseExplorerView extends Action { export class RefreshExplorerView extends Action { - public static readonly ID = 'workbench.files.action.refreshFilesExplorer'; - public static readonly LABEL = nls.localize('refreshExplorer', "Refresh Explorer"); + static readonly ID = 'workbench.files.action.refreshFilesExplorer'; + static readonly LABEL = nls.localize('refreshExplorer', "Refresh Explorer"); constructor( @@ -710,7 +710,7 @@ export class RefreshExplorerView extends Action { })); } - public run(): Promise { + run(): Promise { return this.viewletService.openViewlet(VIEWLET_ID).then(() => this.explorerService.refresh() ); @@ -719,8 +719,8 @@ export class RefreshExplorerView extends Action { export class ShowOpenedFileInNewWindow extends Action { - public static readonly ID = 'workbench.action.files.showOpenedFileInNewWindow'; - public static readonly LABEL = nls.localize('openFileInNewWindow', "Open Active File in New Window"); + static readonly ID = 'workbench.action.files.showOpenedFileInNewWindow'; + static readonly LABEL = nls.localize('openFileInNewWindow', "Open Active File in New Window"); constructor( id: string, @@ -733,7 +733,7 @@ export class ShowOpenedFileInNewWindow extends Action { super(id, label); } - public run(): Promise { + run(): Promise { const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }); if (fileResource) { if (this.fileService.canHandleResource(fileResource)) { @@ -808,8 +808,8 @@ export function getWellFormedFileName(filename: string): string { export class CompareWithClipboardAction extends Action { - public static readonly ID = 'workbench.files.action.compareWithClipboard'; - public static readonly LABEL = nls.localize('compareWithClipboard', "Compare Active File with Clipboard"); + static readonly ID = 'workbench.files.action.compareWithClipboard'; + static readonly LABEL = nls.localize('compareWithClipboard', "Compare Active File with Clipboard"); private static readonly SCHEME = 'clipboardCompare'; @@ -828,7 +828,7 @@ export class CompareWithClipboardAction extends Action { this.enabled = true; } - public run(): Promise { + run(): Promise { const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }); if (resource && (this.fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) { if (!this.registrationDisposal) { @@ -848,7 +848,7 @@ export class CompareWithClipboardAction extends Action { return Promise.resolve(true); } - public dispose(): void { + dispose(): void { super.dispose(); dispose(this.registrationDisposal); diff --git a/src/vs/workbench/services/panel/common/panelService.ts b/src/vs/workbench/services/panel/common/panelService.ts index 13d6a6b54e6..ef626afef88 100644 --- a/src/vs/workbench/services/panel/common/panelService.ts +++ b/src/vs/workbench/services/panel/common/panelService.ts @@ -53,7 +53,7 @@ export interface IPanelService { /** * Returns the progress indicator for the panel bar. */ - getProgressIndicator(id: string): IProgressIndicator | null; + getProgressIndicator(id: string): IProgressIndicator | undefined; /** * Show an activity in a panel. diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index 524a952bd02..6da68dca7a6 100644 --- a/src/vs/workbench/services/progress/browser/progressService.ts +++ b/src/vs/workbench/services/progress/browser/progressService.ts @@ -308,7 +308,7 @@ export class ProgressService extends Disposable implements IProgressService { return this.withCompositeProgress(this.panelService.getProgressIndicator(panelid), task, options); } - private withCompositeProgress

, R = unknown>(progressIndicator: IProgressIndicator | null, task: (progress: IProgress) => P, options: IProgressCompositeOptions): P { + private withCompositeProgress

, R = unknown>(progressIndicator: IProgressIndicator | undefined, task: (progress: IProgress) => P, options: IProgressCompositeOptions): P { let progressRunner: IProgressRunner | undefined = undefined; const promise = task({ diff --git a/src/vs/workbench/services/viewlet/browser/viewlet.ts b/src/vs/workbench/services/viewlet/browser/viewlet.ts index ffc1a81d63a..deebb5b8584 100644 --- a/src/vs/workbench/services/viewlet/browser/viewlet.ts +++ b/src/vs/workbench/services/viewlet/browser/viewlet.ts @@ -23,12 +23,12 @@ export interface IViewletService { /** * Opens a viewlet with the given identifier and pass keyboard focus to it if specified. */ - openViewlet(id: string | undefined, focus?: boolean): Promise; + openViewlet(id: string | undefined, focus?: boolean): Promise; /** - * Returns the current active viewlet or null if none. + * Returns the current active viewlet if any. */ - getActiveViewlet(): IViewlet | null; + getActiveViewlet(): IViewlet | undefined; /** * Returns the id of the default viewlet. @@ -48,7 +48,7 @@ export interface IViewletService { /** * Returns the progress indicator for the side bar. */ - getProgressIndicator(id: string): IProgressIndicator | null; + getProgressIndicator(id: string): IProgressIndicator | undefined; /** * Hide the active viewlet. diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 3d1186ff31a..355b2c62476 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -583,8 +583,8 @@ export class TestViewletService implements IViewletService { onDidViewletOpen = this.onDidViewletOpenEmitter.event; onDidViewletClose = this.onDidViewletCloseEmitter.event; - public openViewlet(id: string, focus?: boolean): Promise { - return Promise.resolve(null!); + public openViewlet(id: string, focus?: boolean): Promise { + return Promise.resolve(undefined); } public getViewlets(): ViewletDescriptor[] { @@ -611,7 +611,7 @@ export class TestViewletService implements IViewletService { } public getProgressIndicator(id: string) { - return null!; + return undefined; } public hideActiveViewlet(): void { } From e9cc9c7847745160dcc6327dd8968540c28c0235 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Oct 2019 10:25:04 +0200 Subject: [PATCH 265/435] debt - make debugging lazy services simpler --- .../common/instantiationService.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts index c3e684f944d..44be0d24797 100644 --- a/src/vs/platform/instantiation/common/instantiationService.ts +++ b/src/vs/platform/instantiation/common/instantiationService.ts @@ -219,13 +219,23 @@ export class InstantiationService implements IInstantiationService { // Return a proxy object that's backed by an idle value. That // strategy is to instantiate services in our idle time or when actually // needed but not when injected into a consumer - const idle = new IdleValue(() => this._createInstance(ctor, args, _trace)); + const idle = new IdleValue(() => this._createInstance(ctor, args, _trace)); return new Proxy(Object.create(null), { - get(_target: T, prop: PropertyKey): any { - return (idle.getValue() as any)[prop]; + get(target: any, key: PropertyKey): any { + if (key in target) { + return target[key]; + } + let obj = idle.getValue(); + let prop = obj[key]; + if (typeof prop !== 'function') { + return prop; + } + prop = prop.bind(obj); + target[key] = prop; + return prop; }, set(_target: T, p: PropertyKey, value: any): boolean { - (idle.getValue() as any)[p] = value; + idle.getValue()[p] = value; return true; } }); From a6ac3e5634702827ce8ec4a711370d6b954fce22 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Oct 2019 10:57:58 +0200 Subject: [PATCH 266/435] Revert "fixes #77837" This reverts commit a8a448d166f66bcedcab350858b959a07b9bdfdb. --- src/vs/workbench/contrib/debug/browser/repl.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index e19bb9c745a..c4774d5c30b 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -80,7 +80,7 @@ interface IPrivateReplService { } function revealLastElement(tree: WorkbenchAsyncDataTree) { - tree.scrollTop = Number.POSITIVE_INFINITY; + tree.scrollTop = tree.scrollHeight - tree.renderHeight; } const sessionsToIgnore = new Set(); @@ -799,6 +799,8 @@ class ReplDelegate implements IListVirtualDelegate { constructor(private configurationService: IConfigurationService) { } getHeight(element: IReplElement): number { + const countNumberOfLines = (str: string) => Math.max(1, (str && str.match(/\r\n|\n/g) || []).length); + // Give approximate heights. Repl has dynamic height so the tree will measure the actual height on its own. const config = this.configurationService.getValue('debug'); const fontSize = config.console.fontSize; @@ -817,13 +819,13 @@ class ReplDelegate implements IListVirtualDelegate { return rowHeight; } - let valueRows = value ? Math.ceil(value.length / 150) : 0; + let valueRows = value ? (countNumberOfLines(value) + Math.floor(value.length / 150)) : 0; return rowHeight * valueRows; } if (element instanceof SimpleReplElement || element instanceof ReplEvaluationInput) { let value = element.value; - let valueRows = Math.ceil(value.length / 150); + let valueRows = countNumberOfLines(value) + Math.floor(value.length / 150); return valueRows * rowHeight; } From bcaa2be1b51441fd11685e599b2704908f25a6f2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Oct 2019 11:03:20 +0200 Subject: [PATCH 267/435] outline progress bar delay is average respone time, some minor polish, fixes #63400 --- .../contrib/outline/browser/outlinePanel.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index 663ecfa53fb..5ce17f17da2 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -445,7 +445,6 @@ export class OutlinePanel extends ViewletPanel { private async _doUpdate(editor: ICodeEditor | undefined, event: IModelContentChangedEvent | undefined): Promise { this._editorDisposables.clear(); - this._progressBar.infinite().show(150); const oldModel = this._tree.getInput(); @@ -458,16 +457,16 @@ export class OutlinePanel extends ViewletPanel { return this._showMessage(localize('no-editor', "The active editor cannot provide outline information.")); } - let textModel = editor.getModel(); - let loadingMessage: IDisposable | undefined; - if (!oldModel) { - loadingMessage = new TimeoutTimer( - () => this._showMessage(localize('loading', "Loading document symbols for '{0}'...", basename(textModel.uri))), - 100 - ); - } + const textModel = editor.getModel(); + const loadingMessage = oldModel && new TimeoutTimer( + () => this._showMessage(localize('loading', "Loading document symbols for '{0}'...", basename(textModel.uri))), + 100 + ); - let createdModel = await OutlinePanel._createOutlineModel(textModel, this._editorDisposables); + const requestDelay = OutlineModel.getRequestDelay(textModel); + this._progressBar.infinite().show(requestDelay); + + const createdModel = await OutlinePanel._createOutlineModel(textModel, this._editorDisposables); dispose(loadingMessage); if (!createdModel) { return; @@ -517,7 +516,7 @@ export class OutlinePanel extends ViewletPanel { newModel = oldModel; } else { let state = this._treeStates.get(newModel.textModel.uri.toString()); - await this._tree.setInput(newModel, state); + this._tree.setInput(newModel, state); } // transfer focus from domNode to the tree From 42ebd1036f767603ee64f81ded72d641fa387338 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 11:13:18 +0200 Subject: [PATCH 268/435] build - use enable-proposed-api in tests --- scripts/test-integration.bat | 4 ++-- scripts/test-integration.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index d557a24edaa..3f3815b4feb 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -29,10 +29,10 @@ call .\scripts\test.bat --runGlob **\*.integrationTest.js %* if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in the extension host -call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index df6219221b7..b63daeb74a7 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -37,8 +37,8 @@ fi ./scripts/test.sh --runGlob **/*.integrationTest.js "$@" # Tests in the extension host -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR From b78fe0cc1e04005faf04b17baf7b7e7fe4d8765b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 11:16:21 +0200 Subject: [PATCH 269/435] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d011529af5..591eb9d6096 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "4553fb95f2fbb4382c38983f9b29ea2076ed1865", + "distro": "2c384ca11c034e0d157292ac6f31039626452040", "author": { "name": "Microsoft Corporation" }, From b8a26a013985ebe9b9978c79309089de95375949 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 11:21:43 +0200 Subject: [PATCH 270/435] debt - tweak proposed API check (#82089) --- .../services/extensions/common/abstractExtensionService.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 65d4c2f70ac..14da9c3b8ad 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -459,9 +459,10 @@ class ProposedApiController { // Make enabled proposed API be lowercase for case insensitive comparison this.enableProposedApiFor = (environmentService.args['enable-proposed-api'] || []).map(id => id.toLowerCase()); - this.enableProposedApiForAll = !environmentService.isBuilt || - (!!environmentService.extensionDevelopmentLocationURI && productService.nameLong !== 'Visual Studio Code') || - (this.enableProposedApiFor.length === 0 && 'enable-proposed-api' in environmentService.args); + this.enableProposedApiForAll = + !environmentService.isBuilt || // always allow proposed API when running out of sources + (!!environmentService.extensionDevelopmentLocationURI && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension + (this.enableProposedApiFor.length === 0 && 'enable-proposed-api' in environmentService.args); // always allow proposed API if --enable-proposed-api is provided without extension ID this.productAllowProposedApi = new Set(); if (isNonEmptyArray(productService.extensionAllowedProposedApi)) { From c270a676156ae06a095f292eb7bc8ec2d8e574b8 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Oct 2019 11:35:33 +0200 Subject: [PATCH 271/435] Terminal should scroll to bottom on reused task terminals fixes #72503 --- src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 2f29f0d229b..4f33f892c3f 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -987,6 +987,7 @@ export class TerminalTaskSystem implements ITaskSystem { throw new Error('Task shell launch configuration should not be undefined here.'); } + terminalToReuse.terminal.scrollToBottom(); terminalToReuse.terminal.reuseTerminal(launchConfigs); if (task.command.presentation && task.command.presentation.clear) { From 46be30ef9a228ba7123503a53a9f6cf014fe2c7b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Oct 2019 12:44:25 +0200 Subject: [PATCH 272/435] renames: source -> from, target -> to, #81746 --- src/vs/vscode.proposed.d.ts | 8 ++++---- .../api/browser/mainThreadLanguageFeatures.ts | 8 ++++---- .../api/common/extHostLanguageFeatures.ts | 4 ++-- src/vs/workbench/api/common/extHostTypes.ts | 20 +++++++++---------- .../callHierarchy/browser/callHierarchy.ts | 8 ++++---- .../browser/callHierarchyTree.ts | 8 ++++---- .../api/extHostApiCommands.test.ts | 8 ++++---- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 99ddb4674fd..cbfedc9a0ee 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -59,14 +59,14 @@ declare module 'vscode' { } export class CallHierarchyIncomingCall { - source: CallHierarchyItem; - sourceRanges: Range[]; + from: CallHierarchyItem; + fromRanges: Range[]; constructor(item: CallHierarchyItem, sourceRanges: Range[]); } export class CallHierarchyOutgoingCall { - sourceRanges: Range[]; - target: CallHierarchyItem; + fromRanges: Range[]; + to: CallHierarchyItem; constructor(item: CallHierarchyItem, sourceRanges: Range[]); } diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 0ea4d540b11..20e4bd2bb02 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -501,8 +501,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } return outgoing.map(([item, sourceRanges]): callh.OutgoingCall => { return { - target: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), - sourceRanges + to: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), + fromRanges: sourceRanges }; }); }, @@ -513,8 +513,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } return incoming.map(([item, sourceRanges]): callh.IncomingCall => { return { - source: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), - sourceRanges + from: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), + fromRanges: sourceRanges }; }); } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 94636f78be5..df94581ec5d 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -1021,7 +1021,7 @@ class CallHierarchyAdapter { if (!calls) { return undefined; } - return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.source), call.sourceRanges.map(typeConvert.Range.from)])); + return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.from), call.fromRanges.map(typeConvert.Range.from)])); } async provideCallsFrom(uri: URI, position: IPosition, token: CancellationToken): Promise<[extHostProtocol.ICallHierarchyItemDto, IRange[]][] | undefined> { @@ -1031,7 +1031,7 @@ class CallHierarchyAdapter { if (!calls) { return undefined; } - return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.target), call.sourceRanges.map(typeConvert.Range.from)])); + return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.to), call.fromRanges.map(typeConvert.Range.from)])); } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 27c39b9f121..1d3a41a2f1d 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1161,22 +1161,22 @@ export class CallHierarchyItem { export class CallHierarchyIncomingCall { - source: vscode.CallHierarchyItem; - sourceRanges: vscode.Range[]; + from: vscode.CallHierarchyItem; + fromRanges: vscode.Range[]; - constructor(item: vscode.CallHierarchyItem, sourceRanges: vscode.Range[]) { - this.sourceRanges = sourceRanges; - this.source = item; + constructor(item: vscode.CallHierarchyItem, fromRanges: vscode.Range[]) { + this.fromRanges = fromRanges; + this.from = item; } } export class CallHierarchyOutgoingCall { - target: vscode.CallHierarchyItem; - sourceRanges: vscode.Range[]; + to: vscode.CallHierarchyItem; + fromRanges: vscode.Range[]; - constructor(item: vscode.CallHierarchyItem, sourceRanges: vscode.Range[]) { - this.sourceRanges = sourceRanges; - this.target = item; + constructor(item: vscode.CallHierarchyItem, fromRanges: vscode.Range[]) { + this.fromRanges = fromRanges; + this.to = item; } } diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.ts index 160662e8ac2..06dbdc22a4b 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.ts @@ -29,13 +29,13 @@ export interface CallHierarchyItem { } export interface IncomingCall { - source: CallHierarchyItem; - sourceRanges: IRange[]; + from: CallHierarchyItem; + fromRanges: IRange[]; } export interface OutgoingCall { - sourceRanges: IRange[]; - target: CallHierarchyItem; + fromRanges: IRange[]; + to: CallHierarchyItem; } export interface CallHierarchyProvider { diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts index 274433e91cf..b35134d13ff 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts @@ -83,8 +83,8 @@ export class DataSource implements IAsyncDataSource { const outgoingCalls = await provideOutgoingCalls(model, position, CancellationToken.None); for (const call of outgoingCalls) { bucket.push(new Call( - call.target, - call.sourceRanges.map(range => ({ range, uri: model.uri })), + call.to, + call.fromRanges.map(range => ({ range, uri: model.uri })), parent )); } @@ -94,8 +94,8 @@ export class DataSource implements IAsyncDataSource { const incomingCalls = await provideIncomingCalls(model, position, CancellationToken.None); for (const call of incomingCalls) { bucket.push(new Call( - call.source, - call.sourceRanges.map(range => ({ range, uri: call.source.uri })), + call.from, + call.fromRanges.map(range => ({ range, uri: call.from.uri })), parent )); } diff --git a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts index c01ed376683..9664bc68bd0 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts @@ -878,12 +878,12 @@ suite('ExtHostLanguageFeatureCommands', function () { let incoming = await commands.executeCommand('vscode.executeCallHierarchyProviderIncomingCalls', model.uri, new types.Position(0, 10)); assert.equal(incoming.length, 1); - assert.ok(incoming[0].source instanceof types.CallHierarchyItem); - assert.equal(incoming[0].source.name, 'IN'); + assert.ok(incoming[0].from instanceof types.CallHierarchyItem); + assert.equal(incoming[0].from.name, 'IN'); let outgoing = await commands.executeCommand('vscode.executeCallHierarchyProviderOutgoingCalls', model.uri, new types.Position(0, 10)); assert.equal(outgoing.length, 1); - assert.ok(outgoing[0].target instanceof types.CallHierarchyItem); - assert.equal(outgoing[0].target.name, 'OUT'); + assert.ok(outgoing[0].to instanceof types.CallHierarchyItem); + assert.equal(outgoing[0].to.name, 'OUT'); }); }); From 807a126a6af835e6c270580394975e8d1b1f0fa8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Oct 2019 12:52:57 +0200 Subject: [PATCH 273/435] remove pseudo breadcrumbs in call hierarchy peek, #81859 --- .../browser/callHierarchyPeek.ts | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts index 7e4d4ac6dac..120633c77e4 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts @@ -295,29 +295,11 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { } localDispose.add(value); - // update: title and subtitle - let node: callHTree.Call | undefined = element; - let names = [element.item.name]; - while (node) { - let parent = this._tree.getParentElement(node); - let name: string; - if (parent instanceof callHTree.Call) { - name = parent.item.name; - node = parent; - } else { - name = this._tree.getInput()!.word; - node = undefined; - } - if (this._direction === CallHierarchyDirection.CallsTo) { - names.push(name); - } else { - names.unshift(name); - } - } + // update: title const title = this._direction === CallHierarchyDirection.CallsFrom ? localize('callFrom', "Calls from '{0}'", this._tree.getInput()!.word) : localize('callsTo', "Callers of '{0}'", this._tree.getInput()!.word); - this.setTitle(title, names.join(' → ')); + this.setTitle(title); })); this._disposables.add(this._editor.onMouseDown(e => { From e80b0f53fa5b937ec6cff23143a656b69726c9c2 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 10:50:29 +0200 Subject: [PATCH 274/435] :lipstick: --- src/vs/editor/common/diff/diffComputer.ts | 70 ++++++++++------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index 67ccd7e5c4e..a5a3bb0bf01 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -15,7 +15,7 @@ function computeDiff(originalSequence: ISequence, modifiedSequence: ISequence, c return diffAlgo.ComputeDiff(pretty); } -class LineMarkerSequence implements ISequence { +class LineSequence implements ISequence { private readonly _lines: string[]; private readonly _startColumns: number[]; @@ -25,8 +25,8 @@ class LineMarkerSequence implements ISequence { let startColumns: number[] = []; let endColumns: number[] = []; for (let i = 0, length = lines.length; i < length; i++) { - startColumns[i] = LineMarkerSequence._getFirstNonBlankColumn(lines[i], 1); - endColumns[i] = LineMarkerSequence._getLastNonBlankColumn(lines[i], 1); + startColumns[i] = getFirstNonBlankColumn(lines[i], 1); + endColumns[i] = getLastNonBlankColumn(lines[i], 1); } this._lines = lines; this._startColumns = startColumns; @@ -45,35 +45,11 @@ class LineMarkerSequence implements ISequence { return i + 1; } - public getStartColumn(i: number): number { - return this._startColumns[i]; - } - public getEndLineNumber(i: number): number { return i + 1; } - public getEndColumn(i: number): number { - return this._endColumns[i]; - } - - public static _getFirstNonBlankColumn(txt: string, defaultValue: number): number { - const r = strings.firstNonWhitespaceIndex(txt); - if (r === -1) { - return defaultValue; - } - return r + 1; - } - - public static _getLastNonBlankColumn(txt: string, defaultValue: number): number { - const r = strings.lastNonWhitespaceIndex(txt); - if (r === -1) { - return defaultValue; - } - return r + 2; - } - - public getCharSequence(shouldIgnoreTrimWhitespace: boolean, startIndex: number, endIndex: number): CharSequence { + public createCharSequence(shouldIgnoreTrimWhitespace: boolean, startIndex: number, endIndex: number): CharSequence { let charCodes: number[] = []; let lineNumbers: number[] = []; let columns: number[] = []; @@ -254,7 +230,7 @@ class LineChange implements ILineChange { this.charChanges = charChanges; } - public static createFromDiffResult(shouldIgnoreTrimWhitespace: boolean, diffChange: IDiffChange, originalLineSequence: LineMarkerSequence, modifiedLineSequence: LineMarkerSequence, continueProcessingPredicate: () => boolean, shouldComputeCharChanges: boolean, shouldPostProcessCharChanges: boolean): LineChange { + public static createFromDiffResult(shouldIgnoreTrimWhitespace: boolean, diffChange: IDiffChange, originalLineSequence: LineSequence, modifiedLineSequence: LineSequence, continueProcessingPredicate: () => boolean, shouldComputeCharChanges: boolean, shouldPostProcessCharChanges: boolean): LineChange { let originalStartLineNumber: number; let originalEndLineNumber: number; let modifiedStartLineNumber: number; @@ -278,8 +254,8 @@ class LineChange implements ILineChange { } if (shouldComputeCharChanges && diffChange.originalLength !== 0 && diffChange.modifiedLength !== 0 && continueProcessingPredicate()) { - const originalCharSequence = originalLineSequence.getCharSequence(shouldIgnoreTrimWhitespace, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1); - const modifiedCharSequence = modifiedLineSequence.getCharSequence(shouldIgnoreTrimWhitespace, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1); + const originalCharSequence = originalLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1); + const modifiedCharSequence = modifiedLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1); let rawChanges = computeDiff(originalCharSequence, modifiedCharSequence, continueProcessingPredicate, true); @@ -313,8 +289,8 @@ export class DiffComputer { private readonly maximumRunTimeMs: number; private readonly originalLines: string[]; private readonly modifiedLines: string[]; - private readonly original: LineMarkerSequence; - private readonly modified: LineMarkerSequence; + private readonly original: LineSequence; + private readonly modified: LineSequence; private computationStartTime: number; @@ -326,8 +302,8 @@ export class DiffComputer { this.maximumRunTimeMs = MAXIMUM_RUN_TIME; this.originalLines = originalLines; this.modifiedLines = modifiedLines; - this.original = new LineMarkerSequence(originalLines); - this.modified = new LineMarkerSequence(modifiedLines); + this.original = new LineSequence(originalLines); + this.modified = new LineSequence(modifiedLines); this.computationStartTime = (new Date()).getTime(); } @@ -409,8 +385,8 @@ export class DiffComputer { // Check the leading whitespace { - let originalStartColumn = LineMarkerSequence._getFirstNonBlankColumn(originalLine, 1); - let modifiedStartColumn = LineMarkerSequence._getFirstNonBlankColumn(modifiedLine, 1); + let originalStartColumn = getFirstNonBlankColumn(originalLine, 1); + let modifiedStartColumn = getFirstNonBlankColumn(modifiedLine, 1); while (originalStartColumn > 1 && modifiedStartColumn > 1) { const originalChar = originalLine.charCodeAt(originalStartColumn - 2); const modifiedChar = modifiedLine.charCodeAt(modifiedStartColumn - 2); @@ -431,8 +407,8 @@ export class DiffComputer { // Check the trailing whitespace { - let originalEndColumn = LineMarkerSequence._getLastNonBlankColumn(originalLine, 1); - let modifiedEndColumn = LineMarkerSequence._getLastNonBlankColumn(modifiedLine, 1); + let originalEndColumn = getLastNonBlankColumn(originalLine, 1); + let modifiedEndColumn = getLastNonBlankColumn(modifiedLine, 1); const originalMaxColumn = originalLine.length + 1; const modifiedMaxColumn = modifiedLine.length + 1; while (originalEndColumn < originalMaxColumn && modifiedEndColumn < modifiedMaxColumn) { @@ -534,3 +510,19 @@ export class DiffComputer { } } + +function getFirstNonBlankColumn(txt: string, defaultValue: number): number { + const r = strings.firstNonWhitespaceIndex(txt); + if (r === -1) { + return defaultValue; + } + return r + 1; +} + +function getLastNonBlankColumn(txt: string, defaultValue: number): number { + const r = strings.lastNonWhitespaceIndex(txt); + if (r === -1) { + return defaultValue; + } + return r + 2; +} From 55610696fea1e9de9e36ccc53599997b2a3c7c15 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 11:14:17 +0200 Subject: [PATCH 275/435] Avoid allocations for ISequence.getElementAtIndex --- src/vs/editor/common/diff/diffComputer.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index a5a3bb0bf01..fb1612fe401 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -18,15 +18,18 @@ function computeDiff(originalSequence: ISequence, modifiedSequence: ISequence, c class LineSequence implements ISequence { private readonly _lines: string[]; + private readonly _trimmedLines: string[]; private readonly _startColumns: number[]; private readonly _endColumns: number[]; constructor(lines: string[]) { let startColumns: number[] = []; let endColumns: number[] = []; + this._trimmedLines = []; for (let i = 0, length = lines.length; i < length; i++) { startColumns[i] = getFirstNonBlankColumn(lines[i], 1); endColumns[i] = getLastNonBlankColumn(lines[i], 1); + this._trimmedLines[i] = lines[i].substring(startColumns[i] - 1, endColumns[i] - 1); } this._lines = lines; this._startColumns = startColumns; @@ -38,7 +41,7 @@ class LineSequence implements ISequence { } public getElementAtIndex(i: number): string { - return this._lines[i].substring(this._startColumns[i] - 1, this._endColumns[i] - 1); + return this._trimmedLines[i]; } public getStartLineNumber(i: number): number { From c4821bf4a00dfa54d9d8f5be076b89ab812c0138 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 11:15:38 +0200 Subject: [PATCH 276/435] Use Int32Array --- src/vs/base/common/diff/diff.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index 6eb26b885af..debec9d7a15 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -86,6 +86,11 @@ export class MyArray { destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i]; } } + public static Copy2(sourceArray: Int32Array, sourceIndex: number, destinationArray: Int32Array, destinationIndex: number, length: number) { + for (let i = 0; i < length; i++) { + destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i]; + } + } } //***************************************************************************** @@ -218,8 +223,8 @@ export class LcsDiff { private ModifiedSequence: ISequence; private ContinueProcessingPredicate: IContinueProcessingPredicate | null; - private m_forwardHistory: number[][]; - private m_reverseHistory: number[][]; + private m_forwardHistory: Int32Array[]; + private m_reverseHistory: Int32Array[]; /** * Constructs the DiffFinder @@ -358,7 +363,7 @@ export class LcsDiff { private WALKTRACE(diagonalForwardBase: number, diagonalForwardStart: number, diagonalForwardEnd: number, diagonalForwardOffset: number, diagonalReverseBase: number, diagonalReverseStart: number, diagonalReverseEnd: number, diagonalReverseOffset: number, - forwardPoints: number[], reversePoints: number[], + forwardPoints: Int32Array, reversePoints: Int32Array, originalIndex: number, originalEnd: number, midOriginalArr: number[], modifiedIndex: number, modifiedEnd: number, midModifiedArr: number[], deltaIsEven: boolean, quitEarlyArr: boolean[]): DiffChange[] { @@ -523,8 +528,8 @@ export class LcsDiff { // The modifiedIndex can be computed mathematically from the originalIndex and the diagonal number. let maxDifferences = (originalEnd - originalStart) + (modifiedEnd - modifiedStart); let numDiagonals = maxDifferences + 1; - let forwardPoints: number[] = new Array(numDiagonals); - let reversePoints: number[] = new Array(numDiagonals); + let forwardPoints = new Int32Array(numDiagonals); + let reversePoints = new Int32Array(numDiagonals); // diagonalForwardBase: Index into forwardPoints of the diagonal which passes through (originalStart, modifiedStart) // diagonalReverseBase: Index into reversePoints of the diagonal which passes through (originalEnd, modifiedEnd) let diagonalForwardBase = (modifiedEnd - modifiedStart); @@ -711,14 +716,14 @@ export class LcsDiff { if (numDifferences <= MaxDifferencesHistory) { // We are allocating space for one extra int, which we fill with // the index of the diagonal base index - let temp: number[] = new Array(diagonalForwardEnd - diagonalForwardStart + 2); + let temp = new Int32Array(diagonalForwardEnd - diagonalForwardStart + 2); temp[0] = diagonalForwardBase - diagonalForwardStart + 1; - MyArray.Copy(forwardPoints, diagonalForwardStart, temp, 1, diagonalForwardEnd - diagonalForwardStart + 1); + MyArray.Copy2(forwardPoints, diagonalForwardStart, temp, 1, diagonalForwardEnd - diagonalForwardStart + 1); this.m_forwardHistory.push(temp); - temp = new Array(diagonalReverseEnd - diagonalReverseStart + 2); + temp = new Int32Array(diagonalReverseEnd - diagonalReverseStart + 2); temp[0] = diagonalReverseBase - diagonalReverseStart + 1; - MyArray.Copy(reversePoints, diagonalReverseStart, temp, 1, diagonalReverseEnd - diagonalReverseStart + 1); + MyArray.Copy2(reversePoints, diagonalReverseStart, temp, 1, diagonalReverseEnd - diagonalReverseStart + 1); this.m_reverseHistory.push(temp); } From 84167ad509d25a93626d48dc0fd373c4e8ceca10 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 11:55:14 +0200 Subject: [PATCH 277/435] Add ISequence.elementsAreEqual --- src/vs/base/common/diff/diff.ts | 30 +++++++++++++++-------- src/vs/base/test/common/diff/diff.test.ts | 16 +----------- src/vs/editor/common/diff/diffComputer.ts | 16 ++++++++++++ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index debec9d7a15..29711b99f19 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -5,21 +5,31 @@ import { DiffChange } from 'vs/base/common/diff/diffChange'; -function createStringSequence(a: string): ISequence { - return { - getLength() { return a.length; }, - getElementAtIndex(pos: number) { return a.charCodeAt(pos); } - }; +export class StringDiffSequence implements ISequence { + + constructor(private source: string) { } + + public getLength() { + return this.source.length; + } + + public getElementAtIndex(i: number) { + return this.source.charCodeAt(i); + } + + public elementsAreEqual(seq1: StringDiffSequence, index1: number, seq2: StringDiffSequence, index2: number) { + return (seq1.source.charCodeAt(index1) === seq2.source.charCodeAt(index2)); + } } export function stringDiff(original: string, modified: string, pretty: boolean): IDiffChange[] { - return new LcsDiff(createStringSequence(original), createStringSequence(modified)).ComputeDiff(pretty); + return new LcsDiff(new StringDiffSequence(original), new StringDiffSequence(modified)).ComputeDiff(pretty); } - export interface ISequence { getLength(): number; getElementAtIndex(index: number): number | string; + elementsAreEqual(seq1: ISequence, index1: number, seq2: ISequence, index2: number): boolean; } export interface IDiffChange { @@ -239,15 +249,15 @@ export class LcsDiff { } private ElementsAreEqual(originalIndex: number, newIndex: number): boolean { - return (this.OriginalSequence.getElementAtIndex(originalIndex) === this.ModifiedSequence.getElementAtIndex(newIndex)); + return this.OriginalSequence.elementsAreEqual(this.OriginalSequence, originalIndex, this.ModifiedSequence, newIndex); } private OriginalElementsAreEqual(index1: number, index2: number): boolean { - return (this.OriginalSequence.getElementAtIndex(index1) === this.OriginalSequence.getElementAtIndex(index2)); + return this.OriginalSequence.elementsAreEqual(this.OriginalSequence, index1, this.OriginalSequence, index2); } private ModifiedElementsAreEqual(index1: number, index2: number): boolean { - return (this.ModifiedSequence.getElementAtIndex(index1) === this.ModifiedSequence.getElementAtIndex(index2)); + return this.ModifiedSequence.elementsAreEqual(this.ModifiedSequence, index1, this.ModifiedSequence, index2); } public ComputeDiff(pretty: boolean): IDiffChange[] { diff --git a/src/vs/base/test/common/diff/diff.test.ts b/src/vs/base/test/common/diff/diff.test.ts index f80a6169f28..7917950884e 100644 --- a/src/vs/base/test/common/diff/diff.test.ts +++ b/src/vs/base/test/common/diff/diff.test.ts @@ -4,21 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { LcsDiff, IDiffChange, ISequence } from 'vs/base/common/diff/diff'; - -class StringDiffSequence implements ISequence { - - constructor(private source: string) { - } - - getLength() { - return this.source.length; - } - - getElementAtIndex(i: number) { - return this.source.charCodeAt(i); - } -} +import { LcsDiff, IDiffChange, StringDiffSequence } from 'vs/base/common/diff/diff'; function createArray(length: number, value: T): T[] { const r: T[] = []; diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index fb1612fe401..4a1669a7a29 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -6,6 +6,7 @@ import { IDiffChange, ISequence, LcsDiff } from 'vs/base/common/diff/diff'; import * as strings from 'vs/base/common/strings'; import { ICharChange, ILineChange } from 'vs/editor/common/editorCommon'; +import { hash } from 'vs/base/common/hash'; const MAXIMUM_RUN_TIME = 5000; // 5 seconds const MINIMUM_MATCHING_CHARACTER_LENGTH = 3; @@ -19,6 +20,7 @@ class LineSequence implements ISequence { private readonly _lines: string[]; private readonly _trimmedLines: string[]; + private readonly _trimmedLinesHash: number[]; private readonly _startColumns: number[]; private readonly _endColumns: number[]; @@ -26,10 +28,12 @@ class LineSequence implements ISequence { let startColumns: number[] = []; let endColumns: number[] = []; this._trimmedLines = []; + this._trimmedLinesHash = []; for (let i = 0, length = lines.length; i < length; i++) { startColumns[i] = getFirstNonBlankColumn(lines[i], 1); endColumns[i] = getLastNonBlankColumn(lines[i], 1); this._trimmedLines[i] = lines[i].substring(startColumns[i] - 1, endColumns[i] - 1); + this._trimmedLinesHash[i] = hash(this._trimmedLines[i]); } this._lines = lines; this._startColumns = startColumns; @@ -44,6 +48,14 @@ class LineSequence implements ISequence { return this._trimmedLines[i]; } + public elementsAreEqual(seq1: LineSequence, index1: number, seq2: LineSequence, index2: number): boolean { + if (seq1._trimmedLinesHash[index1] === seq2._trimmedLinesHash[index2]) { + // hashes are equal + return seq1._trimmedLines[index1] === seq2._trimmedLines[index2]; + } + return false; + } + public getStartLineNumber(i: number): number { return i + 1; } @@ -92,6 +104,10 @@ class CharSequence implements ISequence { return this._charCodes[i]; } + public elementsAreEqual(seq1: CharSequence, index1: number, seq2: CharSequence, index2: number): boolean { + return (seq1.getElementAtIndex(index1) === seq2.getElementAtIndex(index2)); + } + public getStartLineNumber(i: number): number { return this._lineNumbers[i]; } From e57a82771ba9963793c628686164a0400e071a8c Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 12:49:50 +0200 Subject: [PATCH 278/435] Pass the elements to the diff algorithm directly --- src/vs/base/common/diff/diff.ts | 102 ++++++++++++++------- src/vs/base/common/hash.ts | 2 +- src/vs/base/parts/tree/browser/treeView.ts | 11 +-- src/vs/base/test/common/diff/diff.test.ts | 11 +-- src/vs/editor/common/diff/diffComputer.ts | 51 +++-------- 5 files changed, 94 insertions(+), 83 deletions(-) diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index 29711b99f19..0183b199249 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -4,21 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { DiffChange } from 'vs/base/common/diff/diffChange'; +import { stringHash } from 'vs/base/common/hash'; export class StringDiffSequence implements ISequence { constructor(private source: string) { } - public getLength() { - return this.source.length; - } - - public getElementAtIndex(i: number) { - return this.source.charCodeAt(i); - } - - public elementsAreEqual(seq1: StringDiffSequence, index1: number, seq2: StringDiffSequence, index2: number) { - return (seq1.source.charCodeAt(index1) === seq2.source.charCodeAt(index2)); + getElements(): Int32Array | number[] | string[] { + const source = this.source; + const characters = new Int32Array(source.length); + for (let i = 0, len = source.length; i < len; i++) { + characters[i] = source.charCodeAt(i); + } + return characters; } } @@ -27,9 +25,7 @@ export function stringDiff(original: string, modified: string, pretty: boolean): } export interface ISequence { - getLength(): number; - getElementAtIndex(index: number): number | string; - elementsAreEqual(seq1: ISequence, index1: number, seq2: ISequence, index2: number): boolean; + getElements(): Int32Array | number[] | string[]; } export interface IDiffChange { @@ -59,7 +55,7 @@ export interface IDiffChange { } export interface IContinueProcessingPredicate { - (furthestOriginalIndex: number, originalSequence: ISequence, matchLengthOfLongest: number): boolean; + (furthestOriginalIndex: number, matchLengthOfLongest: number): boolean; } // @@ -229,9 +225,13 @@ class DiffChangeHelper { */ export class LcsDiff { - private OriginalSequence: ISequence; - private ModifiedSequence: ISequence; - private ContinueProcessingPredicate: IContinueProcessingPredicate | null; + private readonly ContinueProcessingPredicate: IContinueProcessingPredicate | null; + + private readonly _hasStrings: boolean; + private readonly _originalStringElements: string[]; + private readonly _originalElementsOrHash: Int32Array; + private readonly _modifiedStringElements: string[]; + private readonly _modifiedElementsOrHash: Int32Array; private m_forwardHistory: Int32Array[]; private m_reverseHistory: Int32Array[]; @@ -239,29 +239,67 @@ export class LcsDiff { /** * Constructs the DiffFinder */ - constructor(originalSequence: ISequence, newSequence: ISequence, continueProcessingPredicate: IContinueProcessingPredicate | null = null) { - this.OriginalSequence = originalSequence; - this.ModifiedSequence = newSequence; + constructor(originalSequence: ISequence, modifiedSequence: ISequence, continueProcessingPredicate: IContinueProcessingPredicate | null = null) { this.ContinueProcessingPredicate = continueProcessingPredicate; + const [originalStringElements, originalElementsOrHash, originalHasStrings] = LcsDiff._getElements(originalSequence); + const [modifiedStringElements, modifiedElementsOrHash, modifiedHasStrings] = LcsDiff._getElements(modifiedSequence); + + this._hasStrings = (originalHasStrings && modifiedHasStrings); + this._originalStringElements = originalStringElements; + this._originalElementsOrHash = originalElementsOrHash; + this._modifiedStringElements = modifiedStringElements; + this._modifiedElementsOrHash = modifiedElementsOrHash; + this.m_forwardHistory = []; this.m_reverseHistory = []; } + private static _isStringArray(arr: Int32Array | number[] | string[]): arr is string[] { + return (arr.length > 0 && typeof arr[0] === 'string'); + } + + private static _getElements(sequence: ISequence): [string[], Int32Array, boolean] { + const elements = sequence.getElements(); + + if (LcsDiff._isStringArray(elements)) { + const hashes = new Int32Array(elements.length); + for (let i = 0, len = elements.length; i < len; i++) { + hashes[i] = stringHash(elements[i], 0); + } + return [elements, hashes, true]; + } + + if (elements instanceof Int32Array) { + return [[], elements, false]; + } + + return [[], new Int32Array(elements), false]; + } + private ElementsAreEqual(originalIndex: number, newIndex: number): boolean { - return this.OriginalSequence.elementsAreEqual(this.OriginalSequence, originalIndex, this.ModifiedSequence, newIndex); + if (this._originalElementsOrHash[originalIndex] !== this._modifiedElementsOrHash[newIndex]) { + return false; + } + return (this._hasStrings ? this._originalStringElements[originalIndex] === this._modifiedStringElements[newIndex] : true); } private OriginalElementsAreEqual(index1: number, index2: number): boolean { - return this.OriginalSequence.elementsAreEqual(this.OriginalSequence, index1, this.OriginalSequence, index2); + if (this._originalElementsOrHash[index1] !== this._originalElementsOrHash[index2]) { + return false; + } + return (this._hasStrings ? this._originalStringElements[index1] === this._originalStringElements[index2] : true); } private ModifiedElementsAreEqual(index1: number, index2: number): boolean { - return this.ModifiedSequence.elementsAreEqual(this.ModifiedSequence, index1, this.ModifiedSequence, index2); + if (this._modifiedElementsOrHash[index1] !== this._modifiedElementsOrHash[index2]) { + return false; + } + return (this._hasStrings ? this._modifiedStringElements[index1] === this._modifiedStringElements[index2] : true); } public ComputeDiff(pretty: boolean): IDiffChange[] { - return this._ComputeDiff(0, this.OriginalSequence.getLength() - 1, 0, this.ModifiedSequence.getLength() - 1, pretty); + return this._ComputeDiff(0, this._originalElementsOrHash.length - 1, 0, this._modifiedElementsOrHash.length - 1, pretty); } /** @@ -639,7 +677,7 @@ export class LcsDiff { // Check to see if we should be quitting early, before moving on to the next iteration. let matchLengthOfLongest = ((furthestOriginalIndex - originalStart) + (furthestModifiedIndex - modifiedStart) - numDifferences) / 2; - if (this.ContinueProcessingPredicate !== null && !this.ContinueProcessingPredicate(furthestOriginalIndex, this.OriginalSequence, matchLengthOfLongest)) { + if (this.ContinueProcessingPredicate !== null && !this.ContinueProcessingPredicate(furthestOriginalIndex, matchLengthOfLongest)) { // We can't finish, so skip ahead to generating a result from what we have. quitEarlyArr[0] = true; @@ -765,8 +803,8 @@ export class LcsDiff { // Shift all the changes down first for (let i = 0; i < changes.length; i++) { const change = changes[i]; - const originalStop = (i < changes.length - 1) ? changes[i + 1].originalStart : this.OriginalSequence.getLength(); - const modifiedStop = (i < changes.length - 1) ? changes[i + 1].modifiedStart : this.ModifiedSequence.getLength(); + const originalStop = (i < changes.length - 1) ? changes[i + 1].originalStart : this._originalElementsOrHash.length; + const modifiedStop = (i < changes.length - 1) ? changes[i + 1].modifiedStart : this._modifiedElementsOrHash.length; const checkOriginal = change.originalLength > 0; const checkModified = change.modifiedLength > 0; @@ -841,11 +879,10 @@ export class LcsDiff { } private _OriginalIsBoundary(index: number): boolean { - if (index <= 0 || index >= this.OriginalSequence.getLength() - 1) { + if (index <= 0 || index >= this._originalElementsOrHash.length - 1) { return true; } - const element = this.OriginalSequence.getElementAtIndex(index); - return (typeof element === 'string' && /^\s*$/.test(element)); + return (this._hasStrings && /^\s*$/.test(this._originalStringElements[index])); } private _OriginalRegionIsBoundary(originalStart: number, originalLength: number): boolean { @@ -862,11 +899,10 @@ export class LcsDiff { } private _ModifiedIsBoundary(index: number): boolean { - if (index <= 0 || index >= this.ModifiedSequence.getLength() - 1) { + if (index <= 0 || index >= this._modifiedElementsOrHash.length - 1) { return true; } - const element = this.ModifiedSequence.getElementAtIndex(index); - return (typeof element === 'string' && /^\s*$/.test(element)); + return (this._hasStrings && /^\s*$/.test(this._modifiedStringElements[index])); } private _ModifiedRegionIsBoundary(modifiedStart: number, modifiedLength: number): boolean { diff --git a/src/vs/base/common/hash.ts b/src/vs/base/common/hash.ts index 0a5106d3bd6..1902e82c312 100644 --- a/src/vs/base/common/hash.ts +++ b/src/vs/base/common/hash.ts @@ -36,7 +36,7 @@ function booleanHash(b: boolean, initialHashVal: number): number { return numberHash(b ? 433 : 863, initialHashVal); } -function stringHash(s: string, hashVal: number) { +export function stringHash(s: string, hashVal: number) { hashVal = numberHash(149417, hashVal); for (let i = 0, length = s.length; i < length; i++) { hashVal = numberHash(s.charCodeAt(i), hashVal); diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index e1c832eacb7..ee6a900f23a 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -925,12 +925,11 @@ export class TreeView extends HeightMap { if (!skipDiff) { const lcs = new Diff.LcsDiff( { - getLength: () => previousChildrenIds.length, - getElementAtIndex: (i: number) => previousChildrenIds[i] - }, { - getLength: () => afterModelItems.length, - getElementAtIndex: (i: number) => afterModelItems[i].id - }, + getElements: () => previousChildrenIds + }, + { + getElements: () => afterModelItems.map(item => item.id) + }, null ); diff --git a/src/vs/base/test/common/diff/diff.test.ts b/src/vs/base/test/common/diff/diff.test.ts index 7917950884e..be34bca0556 100644 --- a/src/vs/base/test/common/diff/diff.test.ts +++ b/src/vs/base/test/common/diff/diff.test.ts @@ -109,12 +109,11 @@ suite('Diff - Ported from VS', () => { // doesn't get there first. let predicateCallCount = 0; - let diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, leftSequence, longestMatchSoFar) { + let diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { assert.equal(predicateCallCount, 0); predicateCallCount++; - assert.equal(leftSequence.getLength(), left.length); assert.equal(leftIndex, 1); // cancel processing @@ -130,7 +129,7 @@ suite('Diff - Ported from VS', () => { // Cancel after the first match ('c') - diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, leftSequence, longestMatchSoFar) { + diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { assert(longestMatchSoFar <= 1); // We never see a match of length > 1 // Continue processing as long as there hasn't been a match made. @@ -143,7 +142,7 @@ suite('Diff - Ported from VS', () => { // Cancel after the second match ('d') - diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, leftSequence, longestMatchSoFar) { + diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { assert(longestMatchSoFar <= 2); // We never see a match of length > 2 // Continue processing as long as there hasn't been a match made. @@ -157,7 +156,7 @@ suite('Diff - Ported from VS', () => { // Cancel *one iteration* after the second match ('d') let hitSecondMatch = false; - diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, leftSequence, longestMatchSoFar) { + diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { assert(longestMatchSoFar <= 2); // We never see a match of length > 2 let hitYet = hitSecondMatch; @@ -172,7 +171,7 @@ suite('Diff - Ported from VS', () => { // Cancel after the third and final match ('e') - diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, leftSequence, longestMatchSoFar) { + diff = new LcsDiff(new StringDiffSequence(left), new StringDiffSequence(right), function (leftIndex, longestMatchSoFar) { assert(longestMatchSoFar <= 3); // We never see a match of length > 3 // Continue processing as long as there hasn't been a match made. diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index 4a1669a7a29..c74fb9aa079 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -6,7 +6,6 @@ import { IDiffChange, ISequence, LcsDiff } from 'vs/base/common/diff/diff'; import * as strings from 'vs/base/common/strings'; import { ICharChange, ILineChange } from 'vs/editor/common/editorCommon'; -import { hash } from 'vs/base/common/hash'; const MAXIMUM_RUN_TIME = 5000; // 5 seconds const MINIMUM_MATCHING_CHARACTER_LENGTH = 3; @@ -18,42 +17,28 @@ function computeDiff(originalSequence: ISequence, modifiedSequence: ISequence, c class LineSequence implements ISequence { - private readonly _lines: string[]; - private readonly _trimmedLines: string[]; - private readonly _trimmedLinesHash: number[]; + public readonly lines: string[]; private readonly _startColumns: number[]; private readonly _endColumns: number[]; constructor(lines: string[]) { let startColumns: number[] = []; let endColumns: number[] = []; - this._trimmedLines = []; - this._trimmedLinesHash = []; for (let i = 0, length = lines.length; i < length; i++) { startColumns[i] = getFirstNonBlankColumn(lines[i], 1); endColumns[i] = getLastNonBlankColumn(lines[i], 1); - this._trimmedLines[i] = lines[i].substring(startColumns[i] - 1, endColumns[i] - 1); - this._trimmedLinesHash[i] = hash(this._trimmedLines[i]); } - this._lines = lines; + this.lines = lines; this._startColumns = startColumns; this._endColumns = endColumns; } - public getLength(): number { - return this._lines.length; + public getElements(): Int32Array | number[] | string[] { + const elements: string[] = []; + for (let i = 0, len = this.lines.length; i < len; i++) { + elements[i] = this.lines[i].substring(this._startColumns[i] - 1, this._endColumns[i] - 1); } - - public getElementAtIndex(i: number): string { - return this._trimmedLines[i]; - } - - public elementsAreEqual(seq1: LineSequence, index1: number, seq2: LineSequence, index2: number): boolean { - if (seq1._trimmedLinesHash[index1] === seq2._trimmedLinesHash[index2]) { - // hashes are equal - return seq1._trimmedLines[index1] === seq2._trimmedLines[index2]; - } - return false; + return elements; } public getStartLineNumber(i: number): number { @@ -70,7 +55,7 @@ class LineSequence implements ISequence { let columns: number[] = []; let len = 0; for (let index = startIndex; index <= endIndex; index++) { - const lineContent = this._lines[index]; + const lineContent = this.lines[index]; const startColumn = (shouldIgnoreTrimWhitespace ? this._startColumns[index] : 1); const endColumn = (shouldIgnoreTrimWhitespace ? this._endColumns[index] : lineContent.length + 1); for (let col = startColumn; col < endColumn; col++) { @@ -96,16 +81,8 @@ class CharSequence implements ISequence { this._columns = columns; } - public getLength(): number { - return this._charCodes.length; - } - - public getElementAtIndex(i: number): number { - return this._charCodes[i]; - } - - public elementsAreEqual(seq1: CharSequence, index1: number, seq2: CharSequence, index2: number): boolean { - return (seq1.getElementAtIndex(index1) === seq2.getElementAtIndex(index2)); + public getElements(): Int32Array | number[] | string[] { + return this._charCodes; } public getStartLineNumber(i: number): number { @@ -329,13 +306,13 @@ export class DiffComputer { public computeDiff(): ILineChange[] { - if (this.original.getLength() === 1 && this.original.getElementAtIndex(0).length === 0) { + if (this.original.lines.length === 1 && this.original.lines[0].length === 0) { // empty original => fast path return [{ originalStartLineNumber: 1, originalEndLineNumber: 1, modifiedStartLineNumber: 1, - modifiedEndLineNumber: this.modified.getLength(), + modifiedEndLineNumber: this.modified.lines.length, charChanges: [{ modifiedEndColumn: 0, modifiedEndLineNumber: 0, @@ -349,11 +326,11 @@ export class DiffComputer { }]; } - if (this.modified.getLength() === 1 && this.modified.getElementAtIndex(0).length === 0) { + if (this.modified.lines.length === 1 && this.modified.lines[0].length === 0) { // empty modified => fast path return [{ originalStartLineNumber: 1, - originalEndLineNumber: this.original.getLength(), + originalEndLineNumber: this.original.lines.length, modifiedStartLineNumber: 1, modifiedEndLineNumber: 1, charChanges: [{ From b24844ce9d40ccca6793321cca970836c8def7b6 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 13:55:58 +0200 Subject: [PATCH 279/435] Fixes #72823: Do not compute char changes for huge chunks --- src/vs/editor/common/diff/diffComputer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index c74fb9aa079..ea8e8ab3ef9 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -249,7 +249,8 @@ class LineChange implements ILineChange { modifiedEndLineNumber = modifiedLineSequence.getEndLineNumber(diffChange.modifiedStart + diffChange.modifiedLength - 1); } - if (shouldComputeCharChanges && diffChange.originalLength !== 0 && diffChange.modifiedLength !== 0 && continueProcessingPredicate()) { + if (shouldComputeCharChanges && diffChange.originalLength > 0 && diffChange.originalLength < 20 && diffChange.modifiedLength > 0 && diffChange.modifiedLength < 20 && continueProcessingPredicate()) { + // Compute character changes for diff chunks of at most 20 lines... const originalCharSequence = originalLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1); const modifiedCharSequence = modifiedLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1); From c109bf77ac9dd6128b3382f61d0082ddee40c0e3 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 8 Oct 2019 14:02:44 +0200 Subject: [PATCH 280/435] linux/bin/code.sh: use command -v instead of which --- resources/linux/bin/code.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh index 564f13ef95c..516c05e4ee0 100755 --- a/resources/linux/bin/code.sh +++ b/resources/linux/bin/code.sh @@ -30,7 +30,7 @@ if [ ! -L $0 ]; then # if path is not a symlink, find relatively VSCODE_PATH="$(dirname $0)/.." else - if which readlink >/dev/null; then + if command -v readlink >/dev/null; then # if readlink exists, follow the symlink and find relatively VSCODE_PATH="$(dirname $(readlink -f $0))/.." else From 0fc92f222f9b7007240583c090d5c2c748d91938 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Oct 2019 14:11:33 +0200 Subject: [PATCH 281/435] fix tests --- src/vs/vscode.proposed.d.ts | 4 ++-- .../api/browser/mainThreadLanguageFeatures.ts | 8 ++++---- src/vs/workbench/api/common/extHostApiCommands.ts | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index cbfedc9a0ee..93afe709fbb 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -61,13 +61,13 @@ declare module 'vscode' { export class CallHierarchyIncomingCall { from: CallHierarchyItem; fromRanges: Range[]; - constructor(item: CallHierarchyItem, sourceRanges: Range[]); + constructor(item: CallHierarchyItem, fromRanges: Range[]); } export class CallHierarchyOutgoingCall { fromRanges: Range[]; to: CallHierarchyItem; - constructor(item: CallHierarchyItem, sourceRanges: Range[]); + constructor(item: CallHierarchyItem, fromRanges: Range[]); } export interface CallHierarchyItemProvider { diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 20e4bd2bb02..05bc4303f3e 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -499,10 +499,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha if (!outgoing) { return outgoing; } - return outgoing.map(([item, sourceRanges]): callh.OutgoingCall => { + return outgoing.map(([item, fromRanges]): callh.OutgoingCall => { return { to: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), - fromRanges: sourceRanges + fromRanges }; }); }, @@ -511,10 +511,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha if (!incoming) { return incoming; } - return incoming.map(([item, sourceRanges]): callh.IncomingCall => { + return incoming.map(([item, fromRanges]): callh.IncomingCall => { return { from: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), - fromRanges: sourceRanges + fromRanges }; }); } diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index ff8f8cebe65..ebe9352c103 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -576,30 +576,30 @@ export class ExtHostApiCommands { private async _executeCallHierarchyIncomingCallsProvider(resource: URI, position: types.Position): Promise { type IncomingCallDto = { - source: ICallHierarchyItemDto; - sourceRanges: IRange[]; + from: ICallHierarchyItemDto; + fromRanges: IRange[]; }; const args = { resource, position: typeConverters.Position.from(position) }; const calls = await this._commands.executeCommand('_executeCallHierarchyIncomingCalls', args); const result: vscode.CallHierarchyIncomingCall[] = []; for (const call of calls) { - result.push(new types.CallHierarchyIncomingCall(typeConverters.CallHierarchyItem.to(call.source), call.sourceRanges.map(typeConverters.Range.to))); + result.push(new types.CallHierarchyIncomingCall(typeConverters.CallHierarchyItem.to(call.from), call.fromRanges.map(typeConverters.Range.to))); } return result; } private async _executeCallHierarchyOutgoingCallsProvider(resource: URI, position: types.Position): Promise { type OutgoingCallDto = { - sourceRanges: IRange[]; - target: ICallHierarchyItemDto; + fromRanges: IRange[]; + to: ICallHierarchyItemDto; }; const args = { resource, position: typeConverters.Position.from(position) }; const calls = await this._commands.executeCommand('_executeCallHierarchyOutgoingCalls', args); const result: vscode.CallHierarchyOutgoingCall[] = []; for (const call of calls) { - result.push(new types.CallHierarchyOutgoingCall(typeConverters.CallHierarchyItem.to(call.target), call.sourceRanges.map(typeConverters.Range.to))); + result.push(new types.CallHierarchyOutgoingCall(typeConverters.CallHierarchyItem.to(call.to), call.fromRanges.map(typeConverters.Range.to))); } return result; } From c3e1bcc67b905e83c1084c855f7614142c3e9302 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 14:16:27 +0200 Subject: [PATCH 282/435] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 591eb9d6096..c00bca05c18 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "2c384ca11c034e0d157292ac6f31039626452040", + "distro": "0bc140d5e9879a5dfced1c74c6614373338c6323", "author": { "name": "Microsoft Corporation" }, From 5cd301d4036059e66e5b281d26ffffa0259c3312 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 14:36:13 +0200 Subject: [PATCH 283/435] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c00bca05c18..73de0699d82 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "0bc140d5e9879a5dfced1c74c6614373338c6323", + "distro": "7d62db65536347b7a7c21ae355071b55920c4d84", "author": { "name": "Microsoft Corporation" }, From 273d62f2e7aa53c31d7d60cc810f810dfbfab60b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Oct 2019 14:45:56 +0200 Subject: [PATCH 284/435] Make `files.eol` overridable. Fixes #49418. Fixes #34876 --- .../smartSelect/test/smartSelect.test.ts | 24 +------------------ .../standalone/browser/simpleServices.ts | 10 ++++---- .../test/common/services/modelService.test.ts | 10 ++++---- .../files/browser/files.contribution.ts | 1 + .../keybindingEditing.test.ts | 11 +++++---- .../common/textResourcePropertiesService.ts | 6 ++--- .../workbench/test/workbenchTestServices.ts | 10 ++++---- 7 files changed, 23 insertions(+), 49 deletions(-) diff --git a/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts b/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts index b918921b059..f0eedb8324d 100644 --- a/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts +++ b/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts @@ -12,33 +12,11 @@ import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageCo import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules'; -import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bracketSelections'; import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/smartSelect'; import { CancellationToken } from 'vs/base/common/cancellation'; import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections'; - -class TestTextResourcePropertiesService implements ITextResourcePropertiesService { - - _serviceBrand: undefined; - - constructor( - @IConfigurationService private readonly configurationService: IConfigurationService, - ) { - } - - getEOL(resource: URI | undefined): string { - const filesConfiguration = this.configurationService.getValue<{ eol: string }>('files'); - if (filesConfiguration && filesConfiguration.eol) { - if (filesConfiguration.eol !== 'auto') { - return filesConfiguration.eol; - } - } - return (isLinux || isMacintosh) ? '\n' : '\r\n'; - } -} +import { TestTextResourcePropertiesService } from 'vs/editor/test/common/services/modelService.test'; class MockJSMode extends MockMode { diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 495b81c11dd..121167d45ef 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -515,12 +515,10 @@ export class SimpleResourcePropertiesService implements ITextResourcePropertiesS ) { } - getEOL(resource: URI): string { - const filesConfiguration = this.configurationService.getValue<{ eol: string }>('files'); - if (filesConfiguration && filesConfiguration.eol) { - if (filesConfiguration.eol !== 'auto') { - return filesConfiguration.eol; - } + getEOL(resource: URI, language?: string): string { + const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource }); + if (eol && eol !== 'auto') { + return eol; } return (isLinux || isMacintosh) ? '\n' : '\r\n'; } diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index 20d3b7d3312..0a28a285b38 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -365,7 +365,7 @@ assertComputeEdits(file1, file2); } } -class TestTextResourcePropertiesService implements ITextResourcePropertiesService { +export class TestTextResourcePropertiesService implements ITextResourcePropertiesService { _serviceBrand: undefined; @@ -375,11 +375,9 @@ class TestTextResourcePropertiesService implements ITextResourcePropertiesServic } getEOL(resource: URI, language?: string): string { - const filesConfiguration = this.configurationService.getValue<{ eol: string }>('files', { overrideIdentifier: language, resource }); - if (filesConfiguration && filesConfiguration.eol) { - if (filesConfiguration.eol !== 'auto') { - return filesConfiguration.eol; - } + const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource }); + if (eol && eol !== 'auto') { + return eol; } return (platform.isLinux || platform.isMacintosh) ? '\n' : '\r\n'; } diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 1f4cd95f65d..8afe9ace396 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -253,6 +253,7 @@ configurationRegistry.registerConfiguration({ }, 'files.eol': { 'type': 'string', + 'overridable': true, 'enum': [ '\n', '\r\n', diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index 0b7b04823bd..97a9fcc913b 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -19,7 +19,6 @@ import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService } from 'vs/platform/files/common/files'; @@ -49,6 +48,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; class TestEnvironmentService extends WorkbenchEnvironmentService { @@ -81,11 +81,12 @@ suite('KeybindingsEditing', () => { instantiationService = new TestInstantiationService(); const environmentService = new TestEnvironmentService(URI.file(testDir)); + + const configService = new TestConfigurationService(); + configService.setUserConfiguration('files', { 'eol': '\n' }); + instantiationService.stub(IEnvironmentService, environmentService); - instantiationService.stub(IConfigurationService, ConfigurationService); - instantiationService.stub(IConfigurationService, 'getValue', { 'eol': '\n' }); - instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', () => { }); - instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', () => { }); + instantiationService.stub(IConfigurationService, configService); instantiationService.stub(IWorkspaceContextService, new TestContextService()); const lifecycleService = new TestLifecycleService(); instantiationService.stub(ILifecycleService, lifecycleService); diff --git a/src/vs/workbench/services/textfile/common/textResourcePropertiesService.ts b/src/vs/workbench/services/textfile/common/textResourcePropertiesService.ts index 95495464e6d..ce6bc5f6eba 100644 --- a/src/vs/workbench/services/textfile/common/textResourcePropertiesService.ts +++ b/src/vs/workbench/services/textfile/common/textResourcePropertiesService.ts @@ -30,9 +30,9 @@ export class TextResourcePropertiesService implements ITextResourcePropertiesSer } getEOL(resource?: URI, language?: string): string { - const filesConfiguration = this.configurationService.getValue<{ eol: string }>('files', { overrideIdentifier: language, resource }); - if (filesConfiguration && filesConfiguration.eol && filesConfiguration.eol !== 'auto') { - return filesConfiguration.eol; + const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource }); + if (eol && eol !== 'auto') { + return eol; } const os = this.getOS(resource); return os === OperatingSystem.Linux || os === OperatingSystem.Macintosh ? '\n' : '\r\n'; diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 355b2c62476..803ae1b59af 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1241,12 +1241,10 @@ export class TestTextResourcePropertiesService implements ITextResourcePropertie ) { } - getEOL(resource: URI): string { - const filesConfiguration = this.configurationService.getValue<{ eol: string }>('files'); - if (filesConfiguration && filesConfiguration.eol) { - if (filesConfiguration.eol !== 'auto') { - return filesConfiguration.eol; - } + getEOL(resource: URI, language?: string): string { + const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource }); + if (eol && eol !== 'auto') { + return eol; } return (isLinux || isMacintosh) ? '\n' : '\r\n'; } From daaf92b5bc282d478e5cfb1cab764999fb6accf2 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Oct 2019 14:53:24 +0200 Subject: [PATCH 285/435] [shellscript] Make \n the default eol. Fixes #49418 --- extensions/shellscript/package.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json index a55af2b08ff..211401a070c 100644 --- a/extensions/shellscript/package.json +++ b/extensions/shellscript/package.json @@ -23,6 +23,12 @@ "language": "shellscript", "scopeName": "source.shell", "path": "./syntaxes/shell-unix-bash.tmLanguage.json" - }] + }], + "configurationDefaults": { + "[shellscript]": { + "files.eol": "\n" + } + } + } } From e4a66a86981b65e86486ef433d57fef6c9d18f93 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 14:56:38 +0200 Subject: [PATCH 286/435] strict null --- .../workbench/browser/parts/compositePart.ts | 31 ++-- .../browser/parts/editor/editorGroupView.ts | 151 +++++++++--------- .../browser/parts/panel/panelPart.ts | 2 +- 3 files changed, 98 insertions(+), 86 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index b181734523b..fbc33409d13 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -32,6 +32,7 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Dimension, append, $, addClass, hide, show, addClasses } from 'vs/base/browser/dom'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; +import { assertIsDefined } from 'vs/base/common/types'; export interface ICompositeTitleLabel { @@ -57,15 +58,15 @@ export abstract class CompositePart extends Part { protected readonly onDidCompositeOpen = this._register(new Emitter<{ composite: IComposite, focus: boolean }>()); protected readonly onDidCompositeClose = this._register(new Emitter()); - protected toolBar: ToolBar; + protected toolBar: ToolBar | undefined; private mapCompositeToCompositeContainer = new Map(); private mapActionsBindingToComposite = new Map void>(); private activeComposite: Composite | undefined; private lastActiveCompositeId: string; private instantiatedCompositeItems: Map; - private titleLabel: ICompositeTitleLabel; - private progressBar: ProgressBar; + private titleLabel: ICompositeTitleLabel | undefined; + private progressBar: ProgressBar | undefined; private contentAreaSize: Dimension | undefined; private readonly telemetryActionsListener = this._register(new MutableDisposable()); private currentCompositeOpenToken: string | undefined; @@ -233,7 +234,8 @@ export abstract class CompositePart extends Part { show(compositeContainer); // Setup action runner - this.toolBar.actionRunner = composite.getActionRunner(); + const toolBar = assertIsDefined(this.toolBar); + toolBar.actionRunner = composite.getActionRunner(); // Update title with composite title if it differs from descriptor const descriptor = this.registry.getComposite(composite.getId()); @@ -250,7 +252,7 @@ export abstract class CompositePart extends Part { actionsBinding(); // Action Run Handling - this.telemetryActionsListener.value = this.toolBar.actionRunner.onDidRun(e => { + this.telemetryActionsListener.value = toolBar.actionRunner.onDidRun(e => { // Check for Error if (e.error && !errors.isPromiseCanceledError(e.error)) { @@ -311,7 +313,8 @@ export abstract class CompositePart extends Part { this.titleLabel.updateTitle(compositeId, compositeTitle, (keybinding && keybinding.getLabel()) || undefined); - this.toolBar.setAriaLabel(nls.localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle)); + const toolBar = assertIsDefined(this.toolBar); + toolBar.setAriaLabel(nls.localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle)); } private collectCompositeActions(composite: Composite): () => void { @@ -325,10 +328,11 @@ export abstract class CompositePart extends Part { secondaryActions.push(...this.getSecondaryActions()); // Update context - this.toolBar.context = this.actionsContextProvider(); + const toolBar = assertIsDefined(this.toolBar); + toolBar.context = this.actionsContextProvider(); // Return fn to set into toolbar - return this.toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions)); + return toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions)); } protected getActiveComposite(): IComposite | undefined { @@ -359,10 +363,14 @@ export abstract class CompositePart extends Part { } // Clear any running Progress - this.progressBar.stop().hide(); + if (this.progressBar) { + this.progressBar.stop().hide(); + } // Empty Actions - this.toolBar.setActions([])(); + if (this.toolBar) { + this.toolBar.setActions([])(); + } this.onDidCompositeClose.fire(composite); return composite; @@ -412,7 +420,8 @@ export abstract class CompositePart extends Part { super.updateStyles(); // Forward to title label - this.titleLabel.updateStyles(); + const titleLabel = assertIsDefined(this.titleLabel); + titleLabel.updateStyles(); } protected actionViewItemProvider(action: IAction): IActionViewItem | undefined { diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 9b1c072ff2e..3687fb2cba5 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -95,13 +95,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#endregion private _group: EditorGroup; - private _disposed: boolean; + private _disposed = false; - private active: boolean; - private dimension: Dimension; + private active: boolean | undefined; + private dimension: Dimension | undefined; private _whenRestored: Promise; - private isRestored: boolean; + private isRestored = false; private scopedInstantiationService: IInstantiationService; @@ -143,7 +143,68 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this.disposedEditorsWorker = this._register(new RunOnceWorker(editors => this.handleDisposedEditors(editors), 0)); - this.create(); + //#region create() + { + // Container + addClasses(this.element, 'editor-group-container'); + + // Container listeners + this.registerContainerListeners(); + + // Container toolbar + this.createContainerToolbar(); + + // Container context menu + this.createContainerContextMenu(); + + // Letterpress container + const letterpressContainer = document.createElement('div'); + addClass(letterpressContainer, 'editor-group-letterpress'); + this.element.appendChild(letterpressContainer); + + // Progress bar + this.progressBar = this._register(new ProgressBar(this.element)); + this._register(attachProgressBarStyler(this.progressBar, this.themeService)); + this.progressBar.hide(); + + // Scoped services + const scopedContextKeyService = this._register(this.contextKeyService.createScoped(this.element)); + this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection( + [IContextKeyService, scopedContextKeyService], + [IEditorProgressService, new EditorProgressService(this.progressBar)] + )); + + // Context keys + this.handleGroupContextKeys(scopedContextKeyService); + + // Title container + this.titleContainer = document.createElement('div'); + addClass(this.titleContainer, 'title'); + this.element.appendChild(this.titleContainer); + + // Title control + this.titleAreaControl = this.createTitleAreaControl(); + + // Editor container + this.editorContainer = document.createElement('div'); + addClass(this.editorContainer, 'editor-container'); + this.element.appendChild(this.editorContainer); + + // Editor control + this.editorControl = this._register(this.scopedInstantiationService.createInstance(EditorControl, this.editorContainer, this)); + this._onDidChange.input = this.editorControl.onDidSizeConstraintsChange; + + // Track Focus + this.doTrackFocus(); + + // Update containers + this.updateTitleContainer(); + this.updateContainer(); + + // Update styles + this.updateStyles(); + } + //#endregion this._whenRestored = this.restoreEditors(from); this._whenRestored.then(() => this.isRestored = true); @@ -151,68 +212,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this.registerListeners(); } - private create(): void { - - // Container - addClasses(this.element, 'editor-group-container'); - - // Container listeners - this.registerContainerListeners(); - - // Container toolbar - this.createContainerToolbar(); - - // Container context menu - this.createContainerContextMenu(); - - // Letterpress container - const letterpressContainer = document.createElement('div'); - addClass(letterpressContainer, 'editor-group-letterpress'); - this.element.appendChild(letterpressContainer); - - // Progress bar - this.progressBar = this._register(new ProgressBar(this.element)); - this._register(attachProgressBarStyler(this.progressBar, this.themeService)); - this.progressBar.hide(); - - // Scoped services - const scopedContextKeyService = this._register(this.contextKeyService.createScoped(this.element)); - this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection( - [IContextKeyService, scopedContextKeyService], - [IEditorProgressService, new EditorProgressService(this.progressBar)] - )); - - // Context keys - this.handleGroupContextKeys(scopedContextKeyService); - - // Title container - this.titleContainer = document.createElement('div'); - addClass(this.titleContainer, 'title'); - this.element.appendChild(this.titleContainer); - - // Title control - this.createTitleAreaControl(); - - // Editor container - this.editorContainer = document.createElement('div'); - addClass(this.editorContainer, 'editor-container'); - this.element.appendChild(this.editorContainer); - - // Editor control - this.editorControl = this._register(this.scopedInstantiationService.createInstance(EditorControl, this.editorContainer, this)); - this._onDidChange.input = this.editorControl.onDidSizeConstraintsChange; - - // Track Focus - this.doTrackFocus(); - - // Update containers - this.updateTitleContainer(); - this.updateContainer(); - - // Update styles - this.updateStyles(); - } - private handleGroupContextKeys(contextKeyService: IContextKeyService): void { const groupActiveEditorDirtyContextKey = EditorGroupActiveEditorDirtyContext.bindTo(contextKeyService); const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyService); @@ -404,7 +403,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { toggleClass(this.titleContainer, 'show-file-icons', this.accessor.partOptions.showIcons); } - private createTitleAreaControl(): void { + private createTitleAreaControl(): TitleControl { // Clear old if existing if (this.titleAreaControl) { @@ -418,6 +417,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } else { this.titleAreaControl = this.scopedInstantiationService.createInstance(NoTabsTitleControl, this.titleContainer, this.accessor, this); } + + return this.titleAreaControl; } private async restoreEditors(from: IEditorGroupView | ISerializedEditorGroup | null): Promise { @@ -596,7 +597,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Recreate and layout control this.createTitleAreaControl(); - this.layoutTitleAreaControl(); + if (this.dimension) { + this.layoutTitleAreaControl(this.dimension.width); + } // Ensure to show active editor if any if (this._group.activeEditor) { @@ -1487,12 +1490,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this.editorContainer.style.height = `calc(100% - ${this.titleAreaControl.getPreferredHeight()}px)`; // Forward to controls - this.layoutTitleAreaControl(); + this.layoutTitleAreaControl(width); this.editorControl.layout(new Dimension(this.dimension.width, this.dimension.height - this.titleAreaControl.getPreferredHeight())); } - private layoutTitleAreaControl(): void { - this.titleAreaControl.layout(new Dimension(this.dimension.width, this.titleAreaControl.getPreferredHeight())); + private layoutTitleAreaControl(width: number): void { + this.titleAreaControl.layout(new Dimension(width, this.titleAreaControl.getPreferredHeight())); } relayout(): void { @@ -1520,7 +1523,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } class EditorOpeningEvent implements IEditorOpeningEvent { - private override: () => Promise; + private override: () => Promise | undefined; constructor( private _group: GroupIdentifier, @@ -1545,7 +1548,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent { this.override = callback; } - isPrevented(): () => Promise { + isPrevented(): () => Promise | undefined { return this.override; } } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 651d4254d39..43b7f72a1ca 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -357,7 +357,7 @@ export class PanelPart extends CompositePart implements IPanelService { private getToolbarWidth(): number { const activePanel = this.getActivePanel(); - if (!activePanel) { + if (!activePanel || !this.toolBar) { return 0; } From d9a639a06b17eaecc76e5b82872c1667b30fb912 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 15:00:26 +0200 Subject: [PATCH 287/435] fix hygiene --- src/vs/editor/common/diff/diffComputer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index ea8e8ab3ef9..362ce26d72b 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -37,7 +37,7 @@ class LineSequence implements ISequence { const elements: string[] = []; for (let i = 0, len = this.lines.length; i < len; i++) { elements[i] = this.lines[i].substring(this._startColumns[i] - 1, this._endColumns[i] - 1); - } + } return elements; } From 1cc0b592c234fd9bdaf586e3df54ac36e4ba3281 Mon Sep 17 00:00:00 2001 From: Niklas Mollenhauer Date: Tue, 8 Oct 2019 15:18:42 +0200 Subject: [PATCH 288/435] Remove executable bits from non-executable files --- extensions/git/src/commands.ts | 0 resources/win32/inno-big-125.bmp | Bin resources/win32/inno-big-150.bmp | Bin resources/win32/inno-big-175.bmp | Bin resources/win32/inno-big-200.bmp | Bin resources/win32/inno-big-225.bmp | Bin resources/win32/inno-small-100.bmp | Bin resources/win32/inno-small-125.bmp | Bin resources/win32/inno-small-150.bmp | Bin resources/win32/inno-small-175.bmp | Bin resources/win32/inno-small-200.bmp | Bin resources/win32/inno-small-225.bmp | Bin resources/win32/inno-small-250.bmp | Bin .../processExplorer/media/collapsed.svg | 0 .../processExplorer/media/expanded.svg | 0 .../browser/media/breakpoint-function-disabled.svg | 0 .../media/breakpoint-function-unverified.svg | 0 .../debug/browser/media/breakpoint-function.svg | 0 .../debug/browser/media/current-and-breakpoint.svg | 0 .../contrib/debug/browser/media/current-arrow.svg | 0 .../extensions/browser/media/language-icon.svg | 0 .../contrib/feedback/browser/media/twitter.svg | 0 22 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 extensions/git/src/commands.ts mode change 100755 => 100644 resources/win32/inno-big-125.bmp mode change 100755 => 100644 resources/win32/inno-big-150.bmp mode change 100755 => 100644 resources/win32/inno-big-175.bmp mode change 100755 => 100644 resources/win32/inno-big-200.bmp mode change 100755 => 100644 resources/win32/inno-big-225.bmp mode change 100755 => 100644 resources/win32/inno-small-100.bmp mode change 100755 => 100644 resources/win32/inno-small-125.bmp mode change 100755 => 100644 resources/win32/inno-small-150.bmp mode change 100755 => 100644 resources/win32/inno-small-175.bmp mode change 100755 => 100644 resources/win32/inno-small-200.bmp mode change 100755 => 100644 resources/win32/inno-small-225.bmp mode change 100755 => 100644 resources/win32/inno-small-250.bmp mode change 100755 => 100644 src/vs/code/electron-browser/processExplorer/media/collapsed.svg mode change 100755 => 100644 src/vs/code/electron-browser/processExplorer/media/expanded.svg mode change 100755 => 100644 src/vs/workbench/contrib/debug/browser/media/breakpoint-function-disabled.svg mode change 100755 => 100644 src/vs/workbench/contrib/debug/browser/media/breakpoint-function-unverified.svg mode change 100755 => 100644 src/vs/workbench/contrib/debug/browser/media/breakpoint-function.svg mode change 100755 => 100644 src/vs/workbench/contrib/debug/browser/media/current-and-breakpoint.svg mode change 100755 => 100644 src/vs/workbench/contrib/debug/browser/media/current-arrow.svg mode change 100755 => 100644 src/vs/workbench/contrib/extensions/browser/media/language-icon.svg mode change 100755 => 100644 src/vs/workbench/contrib/feedback/browser/media/twitter.svg diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts old mode 100755 new mode 100644 diff --git a/resources/win32/inno-big-125.bmp b/resources/win32/inno-big-125.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-big-150.bmp b/resources/win32/inno-big-150.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-big-175.bmp b/resources/win32/inno-big-175.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-big-200.bmp b/resources/win32/inno-big-200.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-big-225.bmp b/resources/win32/inno-big-225.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-100.bmp b/resources/win32/inno-small-100.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-125.bmp b/resources/win32/inno-small-125.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-150.bmp b/resources/win32/inno-small-150.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-175.bmp b/resources/win32/inno-small-175.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-200.bmp b/resources/win32/inno-small-200.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-225.bmp b/resources/win32/inno-small-225.bmp old mode 100755 new mode 100644 diff --git a/resources/win32/inno-small-250.bmp b/resources/win32/inno-small-250.bmp old mode 100755 new mode 100644 diff --git a/src/vs/code/electron-browser/processExplorer/media/collapsed.svg b/src/vs/code/electron-browser/processExplorer/media/collapsed.svg old mode 100755 new mode 100644 diff --git a/src/vs/code/electron-browser/processExplorer/media/expanded.svg b/src/vs/code/electron-browser/processExplorer/media/expanded.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/debug/browser/media/breakpoint-function-disabled.svg b/src/vs/workbench/contrib/debug/browser/media/breakpoint-function-disabled.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/debug/browser/media/breakpoint-function-unverified.svg b/src/vs/workbench/contrib/debug/browser/media/breakpoint-function-unverified.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/debug/browser/media/breakpoint-function.svg b/src/vs/workbench/contrib/debug/browser/media/breakpoint-function.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/debug/browser/media/current-and-breakpoint.svg b/src/vs/workbench/contrib/debug/browser/media/current-and-breakpoint.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/debug/browser/media/current-arrow.svg b/src/vs/workbench/contrib/debug/browser/media/current-arrow.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/extensions/browser/media/language-icon.svg b/src/vs/workbench/contrib/extensions/browser/media/language-icon.svg old mode 100755 new mode 100644 diff --git a/src/vs/workbench/contrib/feedback/browser/media/twitter.svg b/src/vs/workbench/contrib/feedback/browser/media/twitter.svg old mode 100755 new mode 100644 From 23059a783ee0dea354b273ab3cd2ca3384ab3bb7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Oct 2019 15:24:45 +0200 Subject: [PATCH 289/435] dev - add husky back for git precommit hooks --- package.json | 1 + yarn.lock | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/package.json b/package.json index 73de0699d82..c1bab1384e9 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "gulp-tslint": "^8.1.3", "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", + "husky": "^0.13.1", "innosetup": "5.6.1", "is": "^3.1.0", "istanbul-lib-coverage": "^2.0.5", diff --git a/yarn.lock b/yarn.lock index 9c27370a796..bfff3c6b843 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1439,6 +1439,11 @@ chromium-pickle-js@^0.2.0: resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -2957,6 +2962,11 @@ find-cache-dir@^1.0.0: make-dir "^1.0.0" pkg-dir "^2.0.0" +find-parent-dir@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -4039,6 +4049,16 @@ https-proxy-agent@2.2.1, https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" +husky@^0.13.1: + version "0.13.4" + resolved "https://registry.yarnpkg.com/husky/-/husky-0.13.4.tgz#48785c5028de3452a51c48c12c4f94b2124a1407" + integrity sha1-SHhcUCjeNFKlHEjBLE+UshJKFAc= + dependencies: + chalk "^1.1.3" + find-parent-dir "^0.3.0" + is-ci "^1.0.9" + normalize-path "^1.0.0" + iconv-lite@0.4.19, iconv-lite@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -4281,6 +4301,13 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-ci@^1.0.9: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== + dependencies: + ci-info "^1.5.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -5744,6 +5771,11 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= + normalize-path@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" From 94adc2a641cc46f2bcadb250a5f8cef405bd9c33 Mon Sep 17 00:00:00 2001 From: Lucas Larson Date: Tue, 8 Oct 2019 10:05:09 -0400 Subject: [PATCH 290/435] Repair npm links (#70325) https://registry.npmjs.org instead of https://registry.npmjs/org --- extensions/npm/README.md | 2 +- extensions/npm/package.nls.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/npm/README.md b/extensions/npm/README.md index a24a7d69d6e..941da175102 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -24,7 +24,7 @@ the hover shown on a script or using the command `Run Selected Npm Script`. ### Others -The extension fetches data from https://registry.npmjs/org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies. +The extension fetches data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies. ## Settings diff --git a/extensions/npm/package.nls.json b/extensions/npm/package.nls.json index 40121b8fa8d..b5e00dd614b 100644 --- a/extensions/npm/package.nls.json +++ b/extensions/npm/package.nls.json @@ -7,7 +7,7 @@ "config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.", "config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.", "config.npm.scriptExplorerAction": "The default click action used in the scripts explorer: `open` or `run`, the default is `open`.", - "config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs/org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.", + "config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.", "npm.parseError": "Npm task detection: failed to parse the file {0}", "taskdef.script": "The npm script to customize.", "taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.", From 7ba9113425fc05ef442421cd251eacdb9e2ad837 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Oct 2019 16:12:33 +0200 Subject: [PATCH 291/435] Update default eol on language change if model has no eol yet --- src/vs/editor/common/services/modelServiceImpl.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 1c9d7a274a9..5b5070184ea 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -218,6 +218,10 @@ export class ModelServiceImpl extends Disposable implements IModelService { } private static _setModelOptionsForModel(model: ITextModel, newOptions: ITextModelCreationOptions, currentOptions: ITextModelCreationOptions): void { + if (currentOptions && currentOptions.defaultEOL !== newOptions.defaultEOL && model.getLineCount() === 1) { + model.setEOL(newOptions.defaultEOL === DefaultEndOfLine.LF ? EndOfLineSequence.LF : EndOfLineSequence.CRLF); + } + if (currentOptions && (currentOptions.detectIndentation === newOptions.detectIndentation) && (currentOptions.insertSpaces === newOptions.insertSpaces) From 3117c154b35d51452f1bf1ea990705dc95b0ca48 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Oct 2019 07:26:09 -0700 Subject: [PATCH 292/435] Update xterm and xterm search Diff: https://github.com/xtermjs/xterm.js/compare/ea922fe...84b56b7 xterm@4.2.0-beta4 - Fix Windows demo - TS 3.6 - Cmd+arrow shouldn't print anything - Release 4.1 - Throw when open is called before attach - Throw when infinity/nan is passed to resize - Use set cursor style for blurred appearance (Fixes #67410) xterm-addon-search@ - Fix search not revealing line below viewport (Fixes #82106) --- package.json | 4 ++-- remote/package.json | 4 ++-- remote/web/package.json | 4 ++-- remote/web/yarn.lock | 16 ++++++++-------- remote/yarn.lock | 16 ++++++++-------- yarn.lock | 16 ++++++++-------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index c1bab1384e9..a66d71711fe 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,8 @@ "vscode-ripgrep": "^1.5.7", "vscode-sqlite3": "4.0.8", "vscode-textmate": "^4.2.2", - "xterm": "4.1.0-beta8", - "xterm-addon-search": "0.2.0", + "xterm": "4.2.0-beta4", + "xterm-addon-search": "0.3.0-beta5", "xterm-addon-web-links": "0.2.0", "yauzl": "^2.9.2", "yazl": "^2.4.3" diff --git a/remote/package.json b/remote/package.json index d65eddd673d..15aaa8f30b1 100644 --- a/remote/package.json +++ b/remote/package.json @@ -20,8 +20,8 @@ "vscode-proxy-agent": "0.4.0", "vscode-ripgrep": "^1.5.7", "vscode-textmate": "^4.2.2", - "xterm": "4.1.0-beta8", - "xterm-addon-search": "0.2.0", + "xterm": "4.2.0-beta4", + "xterm-addon-search": "0.3.0-beta5", "xterm-addon-web-links": "0.2.0", "yauzl": "^2.9.2", "yazl": "^2.4.3" diff --git a/remote/web/package.json b/remote/web/package.json index 01e11a75fb2..db6e5d18e12 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -5,8 +5,8 @@ "onigasm-umd": "^2.2.2", "semver-umd": "^5.5.3", "vscode-textmate": "^4.2.2", - "xterm": "4.1.0-beta8", - "xterm-addon-search": "0.2.0", + "xterm": "4.2.0-beta4", + "xterm-addon-search": "0.3.0-beta5", "xterm-addon-web-links": "0.2.0" } } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index 696c1956a47..759deded50b 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -31,17 +31,17 @@ vscode-textmate@^4.2.2: dependencies: oniguruma "^7.2.0" -xterm-addon-search@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0.tgz#46659c7c33f9fc268ad3e7e6c5824bb2fdb65852" - integrity sha512-C/v2VvFn3hb1qUgjJPo7LxzxNCLBgNJv8n6v/bH2NqPz32/PNUF+IHu0SFf1TaIH+pydUpKXCtob5a/UyZg/+Q== +xterm-addon-search@0.3.0-beta5: + version "0.3.0-beta5" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.3.0-beta5.tgz#fd53d33a77a0235018479c712be8c12f7c0d083a" + integrity sha512-3GkGc4hST35/4hzgnQPLLvQ29WH7MkZ0mUrBE/Vm1IQum7TnMvWPTkGemwM+wAl4tdBmynNccHJlFeQzaQtVUg== xterm-addon-web-links@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.2.0.tgz#b408a0be46211d8d4a0bb5e701d8f3c2bd07d473" integrity sha512-dq81c4Pzli2PgKVBgY2REte9sCVibR3df8AP3SEvCTM9uYFnUFxtxzMTplPnc7+rXabVhFdbU6x+rstIk8HNQg== -xterm@4.1.0-beta8: - version "4.1.0-beta8" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.1.0-beta8.tgz#c1ef323ba336d92f5b52302b66f672dfff75b3ef" - integrity sha512-6lf+XVv0qT285w49P92tSYoUB406jdbgdhnPKNzxCIGtGX8kcwK+pHZ8HncDwcEhmTmI4LZ/WXPGtOQJg+onwg== +xterm@4.2.0-beta4: + version "4.2.0-beta4" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.2.0-beta4.tgz#596577f94a1da372119d192363ea2b19d1f8b50c" + integrity sha512-BmkpxCpqdOJoNdIcddkRT8S65sGjgBbWI0uIJNSnzZvj81OKcraMSTmF/ODw0TF/MDLc33Fx9cpDx/D6lQgl8Q== diff --git a/remote/yarn.lock b/remote/yarn.lock index a081e69b960..b018aafbaab 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -416,20 +416,20 @@ vscode-windows-registry@1.0.2: resolved "https://registry.yarnpkg.com/vscode-windows-registry/-/vscode-windows-registry-1.0.2.tgz#b863e704a6a69c50b3098a55fbddbe595b0c124a" integrity sha512-/CLLvuOSM2Vme2z6aNyB+4Omd7hDxpf4Thrt8ImxnXeQtxzel2bClJpFQvQqK/s4oaXlkBKS7LqVLeZM+uSVIA== -xterm-addon-search@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0.tgz#46659c7c33f9fc268ad3e7e6c5824bb2fdb65852" - integrity sha512-C/v2VvFn3hb1qUgjJPo7LxzxNCLBgNJv8n6v/bH2NqPz32/PNUF+IHu0SFf1TaIH+pydUpKXCtob5a/UyZg/+Q== +xterm-addon-search@0.3.0-beta5: + version "0.3.0-beta5" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.3.0-beta5.tgz#fd53d33a77a0235018479c712be8c12f7c0d083a" + integrity sha512-3GkGc4hST35/4hzgnQPLLvQ29WH7MkZ0mUrBE/Vm1IQum7TnMvWPTkGemwM+wAl4tdBmynNccHJlFeQzaQtVUg== xterm-addon-web-links@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.2.0.tgz#b408a0be46211d8d4a0bb5e701d8f3c2bd07d473" integrity sha512-dq81c4Pzli2PgKVBgY2REte9sCVibR3df8AP3SEvCTM9uYFnUFxtxzMTplPnc7+rXabVhFdbU6x+rstIk8HNQg== -xterm@4.1.0-beta8: - version "4.1.0-beta8" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.1.0-beta8.tgz#c1ef323ba336d92f5b52302b66f672dfff75b3ef" - integrity sha512-6lf+XVv0qT285w49P92tSYoUB406jdbgdhnPKNzxCIGtGX8kcwK+pHZ8HncDwcEhmTmI4LZ/WXPGtOQJg+onwg== +xterm@4.2.0-beta4: + version "4.2.0-beta4" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.2.0-beta4.tgz#596577f94a1da372119d192363ea2b19d1f8b50c" + integrity sha512-BmkpxCpqdOJoNdIcddkRT8S65sGjgBbWI0uIJNSnzZvj81OKcraMSTmF/ODw0TF/MDLc33Fx9cpDx/D6lQgl8Q== yauzl@^2.9.2: version "2.10.0" diff --git a/yarn.lock b/yarn.lock index bfff3c6b843..8b48f5f6231 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9271,20 +9271,20 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm-addon-search@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0.tgz#46659c7c33f9fc268ad3e7e6c5824bb2fdb65852" - integrity sha512-C/v2VvFn3hb1qUgjJPo7LxzxNCLBgNJv8n6v/bH2NqPz32/PNUF+IHu0SFf1TaIH+pydUpKXCtob5a/UyZg/+Q== +xterm-addon-search@0.3.0-beta5: + version "0.3.0-beta5" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.3.0-beta5.tgz#fd53d33a77a0235018479c712be8c12f7c0d083a" + integrity sha512-3GkGc4hST35/4hzgnQPLLvQ29WH7MkZ0mUrBE/Vm1IQum7TnMvWPTkGemwM+wAl4tdBmynNccHJlFeQzaQtVUg== xterm-addon-web-links@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.2.0.tgz#b408a0be46211d8d4a0bb5e701d8f3c2bd07d473" integrity sha512-dq81c4Pzli2PgKVBgY2REte9sCVibR3df8AP3SEvCTM9uYFnUFxtxzMTplPnc7+rXabVhFdbU6x+rstIk8HNQg== -xterm@4.1.0-beta8: - version "4.1.0-beta8" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.1.0-beta8.tgz#c1ef323ba336d92f5b52302b66f672dfff75b3ef" - integrity sha512-6lf+XVv0qT285w49P92tSYoUB406jdbgdhnPKNzxCIGtGX8kcwK+pHZ8HncDwcEhmTmI4LZ/WXPGtOQJg+onwg== +xterm@4.2.0-beta4: + version "4.2.0-beta4" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.2.0-beta4.tgz#596577f94a1da372119d192363ea2b19d1f8b50c" + integrity sha512-BmkpxCpqdOJoNdIcddkRT8S65sGjgBbWI0uIJNSnzZvj81OKcraMSTmF/ODw0TF/MDLc33Fx9cpDx/D6lQgl8Q== y18n@^3.2.1: version "3.2.1" From 9e5c2aca237a67243cb407f77dedc7dd28fc88ea Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 8 Oct 2019 16:57:17 +0200 Subject: [PATCH 293/435] fixes #67814 --- extensions/git/package.json | 24 ++++++++++++++++++++++++ extensions/git/package.nls.json | 1 + extensions/git/src/commands.ts | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/extensions/git/package.json b/extensions/git/package.json index b64dfb4707e..eafc4916439 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -362,6 +362,11 @@ "title": "%command.ignore%", "category": "Git" }, + { + "command": "git.revealInExplorer", + "title": "%command.revealInExplorer%", + "category": "Git" + }, { "command": "git.stashIncludeUntracked", "title": "%command.stashIncludeUntracked%", @@ -507,6 +512,10 @@ "command": "git.restoreCommitTemplate", "when": "false" }, + { + "command": "git.revealInExplorer", + "when": "false" + }, { "command": "git.undoCommit", "when": "config.git.enabled && gitOpenRepositoryCount != 0" @@ -913,6 +922,11 @@ "when": "scmProvider == git && scmResourceGroup == merge", "group": "inline" }, + { + "command": "git.revealInExplorer", + "when": "scmProvider == git && scmResourceGroup == merge", + "group": "2_view" + }, { "command": "git.openFile2", "when": "scmProvider == git && scmResourceGroup == merge && config.git.showInlineOpenFileAction && config.git.openDiffOnClick", @@ -948,6 +962,11 @@ "when": "scmProvider == git && scmResourceGroup == index", "group": "inline" }, + { + "command": "git.revealInExplorer", + "when": "scmProvider == git && scmResourceGroup == index", + "group": "2_view" + }, { "command": "git.openFile2", "when": "scmProvider == git && scmResourceGroup == index && config.git.showInlineOpenFileAction && config.git.openDiffOnClick", @@ -1007,6 +1026,11 @@ "command": "git.ignore", "when": "scmProvider == git && scmResourceGroup == workingTree", "group": "1_modification@3" + }, + { + "command": "git.revealInExplorer", + "when": "scmProvider == git && scmResourceGroup == workingTree", + "group": "2_view" } ], "editor/title": [ diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 6587b65421d..c6a474439f5 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -56,6 +56,7 @@ "command.publish": "Publish Branch", "command.showOutput": "Show Git Output", "command.ignore": "Add to .gitignore", + "command.revealInExplorer": "Reveal in Explorer", "command.stashIncludeUntracked": "Stash (Include Untracked)", "command.stash": "Stash", "command.stashPop": "Pop Stash...", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index d17c27e7c28..fdef8f17989 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2069,6 +2069,19 @@ export class CommandCenter { await this.runByRepository(resources, async (repository, resources) => repository.ignore(resources)); } + @command('git.revealInExplorer') + async revealInExplorer(resourceState: SourceControlResourceState): Promise { + if (!resourceState) { + return; + } + + if (!(resourceState.resourceUri instanceof Uri)) { + return; + } + + await commands.executeCommand('revealInExplorer', resourceState.resourceUri); + } + private async _stash(repository: Repository, includeUntracked = false): Promise { const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0; const noStagedChanges = repository.indexGroup.resourceStates.length === 0; From 465d9489d2c239777e25de0580dac082fb4c3625 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Oct 2019 08:13:28 -0700 Subject: [PATCH 294/435] Attach element before calling open in test --- .../electron-browser/terminalCommandTracker.test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts index fefece531e3..bdaf6d62248 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts @@ -84,7 +84,9 @@ suite('Workbench - TerminalCommandTracker', () => { (window).matchMedia = () => { return { addListener: () => { } }; }; - xterm.open(document.createElement('div')); + const e = document.createElement('div'); + document.body.appendChild(e); + xterm.open(e); await writePromise(xterm, '\r0'); await writePromise(xterm, '\n\r1'); @@ -109,12 +111,16 @@ suite('Workbench - TerminalCommandTracker', () => { assert.equal(xterm.getSelection(), '2'); commandTracker.selectToNextCommand(); assert.equal(xterm.getSelection(), isWindows ? '\r\n' : '\n'); + + document.body.removeChild(e); }); test('should select to the next and previous lines & commands', async () => { (window).matchMedia = () => { return { addListener: () => { } }; }; - xterm.open(document.createElement('div')); + const e = document.createElement('div'); + document.body.appendChild(e); + xterm.open(e); await writePromise(xterm, '\r0'); await writePromise(xterm, '\n\r1'); @@ -144,6 +150,8 @@ suite('Workbench - TerminalCommandTracker', () => { assert.equal(xterm.getSelection(), isWindows ? '1\r\n2' : '1\n2'); commandTracker.selectToPreviousLine(); assert.equal(xterm.getSelection(), isWindows ? '0\r\n1\r\n2' : '0\n1\n2'); + + document.body.removeChild(e); }); }); }); From 52649cbefe9a3081ab1a63311aa3ba2d617c0de1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Oct 2019 08:36:39 -0700 Subject: [PATCH 295/435] Call open on Terminal after attach to DOM --- .../workbench/contrib/terminal/browser/terminalInstance.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index ef6bdddec6f..9d167923792 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -561,7 +561,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Attach the xterm object to the DOM, exposing it to the smoke tests this._wrapperElement.xterm = this._xterm; + this._wrapperElement.appendChild(this._xtermElement); + this._container.appendChild(this._wrapperElement); xterm.open(this._xtermElement); + xterm.textarea.addEventListener('focus', () => this._onFocus.fire(this)); xterm.attachCustomKeyEventHandler((event: KeyboardEvent): boolean => { // Disable all input if the terminal is exiting @@ -638,9 +641,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._refreshSelectionContextKey(); })); - this._wrapperElement.appendChild(this._xtermElement); - this._container.appendChild(this._wrapperElement); - const widgetManager = new TerminalWidgetManager(this._wrapperElement); this._widgetManager = widgetManager; this._processManager.onProcessReady(() => { From eb9fe80de689451602f60bba0cf56f87edf7de91 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Oct 2019 17:39:43 +0200 Subject: [PATCH 296/435] when editing c#, typing /* causes */ to be injected. Fixes #43989 --- extensions/csharp/language-configuration.json | 5 ++--- extensions/json/language-configuration.json | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/extensions/csharp/language-configuration.json b/extensions/csharp/language-configuration.json index 88107685266..d8698b46c09 100644 --- a/extensions/csharp/language-configuration.json +++ b/extensions/csharp/language-configuration.json @@ -13,8 +13,7 @@ ["[", "]"], ["(", ")"], { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, - { "open": "/*", "close": " */", "notIn": ["string"] } + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] } ], "surroundingPairs": [ ["{", "}"], @@ -30,4 +29,4 @@ "end": "^\\s*#endregion\\b" } } -} \ No newline at end of file +} diff --git a/extensions/json/language-configuration.json b/extensions/json/language-configuration.json index 9a73ac64aae..7faa70cef7a 100644 --- a/extensions/json/language-configuration.json +++ b/extensions/json/language-configuration.json @@ -12,8 +12,7 @@ { "open": "[", "close": "]", "notIn": ["string"] }, { "open": "(", "close": ")", "notIn": ["string"] }, { "open": "'", "close": "'", "notIn": ["string"] }, - { "open": "/*", "close": "*/", "notIn": ["string"] }, { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, { "open": "`", "close": "`", "notIn": ["string", "comment"] } ] -} \ No newline at end of file +} From 002e2192b5c740afeb647244a48da75caa97c90e Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 8 Oct 2019 17:51:53 +0200 Subject: [PATCH 297/435] Fixes #74722: When there is a selection, never paste on new line --- .../common/controller/cursorTypeOperations.ts | 9 +++------ .../test/browser/controller/cursor.test.ts | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 9fc69bc842e..0df564775fd 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -81,15 +81,12 @@ export class TypeOperations { const selection = selections[i]; let position = selection.getPosition(); + if (pasteOnNewLine && !selection.isEmpty()) { + pasteOnNewLine = false; + } if (pasteOnNewLine && text.indexOf('\n') !== text.length - 1) { pasteOnNewLine = false; } - if (pasteOnNewLine && selection.startLineNumber !== selection.endLineNumber) { - pasteOnNewLine = false; - } - if (pasteOnNewLine && selection.startColumn === model.getLineMinColumn(selection.startLineNumber) && selection.endColumn === model.getLineMaxColumn(selection.startLineNumber)) { - pasteOnNewLine = false; - } if (pasteOnNewLine) { // Paste entire line at the beginning of line diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 984a1e23856..0a8680d8557 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -1494,6 +1494,25 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #74722: Pasting whole line does not replace selection', () => { + usingCursor({ + text: [ + 'line1', + 'line sel 2', + 'line3' + ], + }, (model, cursor) => { + cursor.setSelections('test', [new Selection(2, 6, 2, 9)]); + + cursorCommand(cursor, H.Paste, { text: 'line1\n', pasteOnNewLine: true }); + + assert.equal(model.getLineContent(1), 'line1'); + assert.equal(model.getLineContent(2), 'line line1'); + assert.equal(model.getLineContent(3), ' 2'); + assert.equal(model.getLineContent(4), 'line3'); + }); + }); + test('issue #4996: Multiple cursor paste pastes contents of all cursors', () => { usingCursor({ text: [ From 65f5f14ff7596f4fa32a05038f9c922dd63dbc64 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 8 Oct 2019 18:02:33 +0200 Subject: [PATCH 298/435] change scm default from tree to list --- src/vs/workbench/contrib/scm/browser/scm.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index a8888407cb8..f1aafca78f4 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -114,7 +114,7 @@ Registry.as(ConfigurationExtensions.Configuration).regis localize('scm.defaultViewMode.list', "Show the repository changes as a list.") ], description: localize('scm.defaultViewMode', "Controls the default Source Control repository view mode."), - default: 'tree' + default: 'list' } } }); From ab713cac34e15eaf4e2ac045376f09d9fe7f267b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 8 Oct 2019 18:30:09 +0200 Subject: [PATCH 299/435] fixes #68713 --- src/vs/base/browser/ui/list/listPaging.ts | 8 +++ src/vs/base/browser/ui/list/listView.ts | 2 +- src/vs/base/browser/ui/list/listWidget.ts | 2 +- src/vs/base/browser/ui/tree/abstractTree.ts | 2 +- .../workbench/browser/actions/listCommands.ts | 69 +++++++++++++++++++ 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index 6f0ea59ff10..420b75b9437 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -155,6 +155,14 @@ export class PagedList implements IDisposable { this.list.scrollTop = scrollTop; } + get scrollLeft(): number { + return this.list.scrollTop; + } + + set scrollLeft(scrollLeft: number) { + this.list.scrollLeft = scrollLeft; + } + open(indexes: number[], browserEvent?: UIEvent): void { this.list.open(indexes, browserEvent); } diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 937fc0c870d..97ec6f37206 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -686,7 +686,7 @@ export class ListView implements ISpliceable, IDisposable { return scrollPosition.scrollLeft; } - setScrollLeftt(scrollLeft: number): void { + setScrollLeft(scrollLeft: number): void { if (this.scrollableElementUpdateDisposable) { this.scrollableElementUpdateDisposable.dispose(); this.scrollableElementUpdateDisposable = null; diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index a8a2a63da47..a70969206fb 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -1316,7 +1316,7 @@ export class List implements ISpliceable, IDisposable { } set scrollLeft(scrollLeft: number) { - this.view.setScrollLeftt(scrollLeft); + this.view.setScrollLeft(scrollLeft); } get scrollHeight(): number { diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 925a9128552..e0376d8a519 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -1368,7 +1368,7 @@ export abstract class AbstractTree implements IDisposable } get scrollLeft(): number { - return this.view.scrollTop; + return this.view.scrollLeft; } set scrollLeft(scrollLeft: number) { diff --git a/src/vs/workbench/browser/actions/listCommands.ts b/src/vs/workbench/browser/actions/listCommands.ts index d33cb450d5d..81fb3c49efe 100644 --- a/src/vs/workbench/browser/actions/listCommands.ts +++ b/src/vs/workbench/browser/actions/listCommands.ts @@ -17,6 +17,11 @@ import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; import { DataTree } from 'vs/base/browser/ui/tree/dataTree'; import { ITreeNode } from 'vs/base/browser/ui/tree/tree'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; + +function isLegacyTree(widget: ListWidget): widget is ITree { + return widget instanceof Tree; +} function ensureDOMFocus(widget: ListWidget | undefined): void { // it can happen that one of the commands is executed while @@ -833,3 +838,67 @@ CommandsRegistry.registerCommand({ } } }); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'list.scrollUp', + weight: KeybindingWeight.WorkbenchContrib, + when: WorkbenchListFocusContextKey, + primary: KeyMod.CtrlCmd | KeyCode.UpArrow, + handler: accessor => { + const focused = accessor.get(IListService).lastFocusedList; + + if (!focused || isLegacyTree(focused)) { + return; + } + + focused.scrollTop -= 10; + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'list.scrollDown', + weight: KeybindingWeight.WorkbenchContrib, + when: WorkbenchListFocusContextKey, + primary: KeyMod.CtrlCmd | KeyCode.DownArrow, + handler: accessor => { + const focused = accessor.get(IListService).lastFocusedList; + + if (!focused || isLegacyTree(focused)) { + return; + } + + focused.scrollTop += 10; + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'list.scrollLeft', + weight: KeybindingWeight.WorkbenchContrib, + when: WorkbenchListFocusContextKey, + primary: KeyMod.CtrlCmd | KeyCode.LeftArrow, + handler: accessor => { + const focused = accessor.get(IListService).lastFocusedList; + + if (!focused || isLegacyTree(focused)) { + return; + } + + focused.scrollLeft -= 10; + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'list.scrollRight', + weight: KeybindingWeight.WorkbenchContrib, + when: WorkbenchListFocusContextKey, + primary: KeyMod.CtrlCmd | KeyCode.RightArrow, + handler: accessor => { + const focused = accessor.get(IListService).lastFocusedList; + + if (!focused || isLegacyTree(focused)) { + return; + } + + focused.scrollLeft += 10; + } +}); From 4fe99879254035b9776df33687ff05ebeaca59c2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Oct 2019 09:38:29 -0700 Subject: [PATCH 300/435] Support chords in terminal Fixes #44764 --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 9d167923792..8790a25a7f5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -576,7 +576,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // within commandsToSkipShell const standardKeyboardEvent = new StandardKeyboardEvent(event); const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); - if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { + if (resolveResult && (resolveResult.enterChord || this._skipTerminalCommands.some(k => k === resolveResult.commandId))) { event.preventDefault(); return false; } From 877ce7ac034390e31c5ecebccbb0683bd2c51c3d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Oct 2019 09:45:22 -0700 Subject: [PATCH 301/435] Introduce allowChords setting Fixes #44764 --- .../contrib/terminal/browser/terminal.contribution.ts | 5 +++++ .../workbench/contrib/terminal/browser/terminalInstance.ts | 3 ++- src/vs/workbench/contrib/terminal/common/terminal.ts | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index eae307ef62c..841a2b59bfe 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -251,6 +251,11 @@ configurationRegistry.registerConfiguration({ }, default: [] }, + 'terminal.integrated.allowChords': { + markdownDescription: nls.localize('terminal.integrated.allowChords', "Whether or not to allow chord keybindings in the terminal. Note that when this is true and the keystroke results in a chord it will bypass `terminal.integrated.commandsToSkipShell`, setting this to false is particularly useful when you want ctrl+k to go to your shell (not VS Code)."), + type: 'boolean', + default: true + }, 'terminal.integrated.inheritEnv': { markdownDescription: nls.localize('terminal.integrated.inheritEnv', "Whether new shells should inherit their environment from VS Code. This is not supported on Windows."), type: 'boolean', diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 8790a25a7f5..b9eed7e31ec 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -576,7 +576,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // within commandsToSkipShell const standardKeyboardEvent = new StandardKeyboardEvent(event); const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); - if (resolveResult && (resolveResult.enterChord || this._skipTerminalCommands.some(k => k === resolveResult.commandId))) { + const allowChords = resolveResult && resolveResult.enterChord && this._configHelper.config.allowChords; + if (allowChords || resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { event.preventDefault(); return false; } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 444ac1b408f..f587dbc700f 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -101,6 +101,7 @@ export interface ITerminalConfiguration { detectLocale: 'auto' | 'off' | 'on'; scrollback: number; commandsToSkipShell: string[]; + allowChords: boolean; cwd: string; confirmOnExit: boolean; enableBell: boolean; From bd576990da29319b90d4510f7d50c59db82d096e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 11:27:40 -0700 Subject: [PATCH 302/435] More strict parsing of codicons --- .../browser/ui/codiconLabel/codiconLabel.ts | 2 +- .../browser/ui/octiconLabel/octiconLabel.ts | 2 +- src/vs/base/common/octicon.ts | 17 +++++++++++++---- src/vs/base/test/common/octicon.test.ts | 6 +++--- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codiconLabel.ts b/src/vs/base/browser/ui/codiconLabel/codiconLabel.ts index 42d38948e88..e496fd3a164 100644 --- a/src/vs/base/browser/ui/codiconLabel/codiconLabel.ts +++ b/src/vs/base/browser/ui/codiconLabel/codiconLabel.ts @@ -8,7 +8,7 @@ import 'vs/css!./codicon/codicon-animations'; import { escape } from 'vs/base/common/strings'; function expand(text: string): string { - return text.replace(/\$\(((.+?)(~(.*?))?)\)/g, (_match, _g1, name, _g3, animation) => { + return text.replace(/\$\((([a-z0-9\-]+?)(~([a-z0-9\-]*?))?)\)/gi, (_match, _g1, name, _g3, animation) => { return ``; }); } diff --git a/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts b/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts index c5d77ed9724..209ba4133f5 100644 --- a/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts +++ b/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts @@ -8,7 +8,7 @@ import 'vs/css!./octicons/octicons-animations'; import { escape } from 'vs/base/common/strings'; function expand(text: string): string { - return text.replace(/\$\(((.+?)(~(.*?))?)\)/g, (_match, _g1, name, _g3, animation) => { + return text.replace(/\$\((([a-z0-9\-]+?)(~([a-z0-9\-]*?))?)\)/gi, (_match, _g1, name, _g3, animation) => { return ``; }); } diff --git a/src/vs/base/common/octicon.ts b/src/vs/base/common/octicon.ts index 48da86f6cc1..80b5653f32e 100644 --- a/src/vs/base/common/octicon.ts +++ b/src/vs/base/common/octicon.ts @@ -9,8 +9,8 @@ import { ltrim } from 'vs/base/common/strings'; const octiconStartMarker = '$('; export interface IParsedOcticons { - text: string; - octiconOffsets?: number[]; + readonly text: string; + readonly octiconOffsets?: readonly number[]; } export function parseOcticons(text: string): IParsedOcticons { @@ -78,7 +78,16 @@ function doParseOcticons(text: string, firstOcticonIndex: number): IParsedOctico // within octicon else if (currentOcticonStart !== -1) { - currentOcticonValue += char; + // Make sure this is a real octicon name + if (/^[a-z0-9\-]$/i.test(char)) { + currentOcticonValue += char; + } else { + // This is not a real octicon, treat it as text + appendChars(currentOcticonValue); + + currentOcticonStart = -1; + currentOcticonValue = ''; + } } // any value outside of octicons @@ -123,4 +132,4 @@ export function matchesFuzzyOcticonAware(query: string, target: IParsedOcticons, } return matches; -} \ No newline at end of file +} diff --git a/src/vs/base/test/common/octicon.test.ts b/src/vs/base/test/common/octicon.test.ts index c91055525d2..8ba48579337 100644 --- a/src/vs/base/test/common/octicon.test.ts +++ b/src/vs/base/test/common/octicon.test.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import { IMatch } from 'vs/base/common/filters'; -import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon'; +import { matchesFuzzyOcticonAware, parseOcticons, IParsedOcticons } from 'vs/base/common/octicon'; export interface IOcticonFilter { // Returns null if word doesn't match. - (query: string, target: { text: string, octiconOffsets?: number[] }): IMatch[] | null; + (query: string, target: IParsedOcticons): IMatch[] | null; } -function filterOk(filter: IOcticonFilter, word: string, target: { text: string, octiconOffsets?: number[] }, highlights?: { start: number; end: number; }[]) { +function filterOk(filter: IOcticonFilter, word: string, target: IParsedOcticons, highlights?: { start: number; end: number; }[]) { let r = filter(word, target); assert(r); if (highlights) { From 4332203005d995493fb649060d3af21250fb2b54 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Oct 2019 21:02:14 +0200 Subject: [PATCH 303/435] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a66d71711fe..54f2ca80a16 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "7d62db65536347b7a7c21ae355071b55920c4d84", + "distro": "308af76bb026217c70081d07b44af5cd640c6f8b", "author": { "name": "Microsoft Corporation" }, From 90b66c889cda34718110204df563154b6da9fe20 Mon Sep 17 00:00:00 2001 From: JavaScript Joe Date: Tue, 8 Oct 2019 16:32:39 -0700 Subject: [PATCH 304/435] fix: remove TypeScript from ExtensionSuggestions (#82125) * fix: remove TypeScript from ExtensionSuggestions * fix: remove TS ExtensionSuggestion completely --- src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts index f4a36a39767..b293a6d68b8 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts @@ -146,7 +146,6 @@ interface ExtensionSuggestion { const extensionPacks: ExtensionSuggestion[] = [ { name: localize('welcomePage.javaScript', "JavaScript"), id: 'dbaeumer.vscode-eslint' }, - { name: localize('welcomePage.typeScript', "TypeScript"), id: 'ms-vscode.vscode-typescript-tslint-plugin' }, { name: localize('welcomePage.python', "Python"), id: 'ms-python.python' }, // { name: localize('welcomePage.go', "Go"), id: 'lukehoban.go' }, { name: localize('welcomePage.php', "PHP"), id: 'felixfbecker.php-pack' }, From 20654cccf104036bf2ed2309bbfb138e07db4539 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 11:45:11 -0700 Subject: [PATCH 305/435] Marking IMarkdownString.value and isTrusted as readonly --- src/vs/base/common/htmlContent.ts | 30 +++++++++++-------- src/vs/editor/contrib/links/links.ts | 3 +- src/vs/monaco.d.ts | 4 +-- .../api/common/extHostTypeConverters.ts | 4 +-- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index fee84c57bf6..c9bfed7ea8f 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -7,23 +7,27 @@ import { equals } from 'vs/base/common/arrays'; import { UriComponents } from 'vs/base/common/uri'; export interface IMarkdownString { - value: string; - isTrusted?: boolean; + readonly value: string; + readonly isTrusted?: boolean; uris?: { [href: string]: UriComponents }; } export class MarkdownString implements IMarkdownString { - value: string; - isTrusted?: boolean; + private _value: string; + private _isTrusted: boolean; - constructor(value: string = '') { - this.value = value; + constructor(value: string = '', isTrusted = false) { + this._value = value; + this._isTrusted = isTrusted; } + get value() { return this._value; } + get isTrusted() { return this._isTrusted; } + appendText(value: string): MarkdownString { // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash - this.value += value + this._value += value .replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') .replace('\n', '\n\n'); @@ -31,16 +35,16 @@ export class MarkdownString implements IMarkdownString { } appendMarkdown(value: string): MarkdownString { - this.value += value; + this._value += value; return this; } appendCodeblock(langId: string, code: string): MarkdownString { - this.value += '\n```'; - this.value += langId; - this.value += '\n'; - this.value += code; - this.value += '\n```\n'; + this._value += '\n```'; + this._value += langId; + this._value += '\n'; + this._value += code; + this._value += '\n```\n'; return this; } } diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index a387d6cd9db..184fa18ecf0 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -44,8 +44,7 @@ function getHoverMessage(link: Link, useMetaKey: boolean): MarkdownString { : nls.localize('links.navigate.kb.alt', "alt + click"); if (link.url) { - const hoverMessage = new MarkdownString().appendMarkdown(`[${label}](${link.url.toString()}) (${kb})`); - hoverMessage.isTrusted = true; + const hoverMessage = new MarkdownString('', true).appendMarkdown(`[${label}](${link.url.toString()}) (${kb})`); return hoverMessage; } else { return new MarkdownString().appendText(`${label} (${kb})`); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index cfb897053b2..697d44580c1 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -379,8 +379,8 @@ declare namespace monaco { } export interface IMarkdownString { - value: string; - isTrusted?: boolean; + readonly value: string; + readonly isTrusted?: boolean; uris?: { [href: string]: UriComponents; }; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 0c9236b67af..608b6d90707 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -303,9 +303,7 @@ export namespace MarkdownString { } export function to(value: htmlContent.IMarkdownString): vscode.MarkdownString { - const ret = new htmlContent.MarkdownString(value.value); - ret.isTrusted = value.isTrusted; - return ret; + return new htmlContent.MarkdownString(value.value, value.isTrusted); } export function fromStrict(value: string | types.MarkdownString): undefined | string | htmlContent.IMarkdownString { From 82599cc6bd6f979d9584c190cc15c25bf78f05d2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 15:37:21 -0700 Subject: [PATCH 306/435] Add extra clairification about where displayName is used Fixes #81827 --- src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts index c5c85509532..0ab4cbd7514 100644 --- a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts @@ -41,7 +41,7 @@ const webviewEditorsContribution: IJSONSchema = { }, [WebviewEditorContribution.displayName]: { type: 'string', - description: nls.localize('contributes.displayName', 'Name of the custom editor displayed to users.'), + description: nls.localize('contributes.displayName', 'Human readable name of the custom editor. This is displayed to users when selecting which editor to use.'), }, [WebviewEditorContribution.selector]: { type: 'array', From 9502b4c3903cc6360eacd2a70129b9efe9426e95 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 16:14:07 -0700 Subject: [PATCH 307/435] Only enable re-open with command when we actually have a custom editor for the current resource Fixes #81831 --- .../contrib/customEditor/browser/commands.ts | 7 ++-- .../customEditor/browser/customEditors.ts | 39 ++++++++++++++++--- .../customEditor/common/customEditor.ts | 3 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/commands.ts b/src/vs/workbench/contrib/customEditor/browser/commands.ts index 44ff3ec8490..996aa3ceb7e 100644 --- a/src/vs/workbench/contrib/customEditor/browser/commands.ts +++ b/src/vs/workbench/contrib/customEditor/browser/commands.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// import { Schemas } from 'vs/base/common/network'; import { firstOrDefault } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -13,8 +12,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IListService } from 'vs/platform/list/browser/listService'; import { IEditorCommandsContext } from 'vs/workbench/common/editor'; -// import { ResourceContextKey } from 'vs/workbench/common/resources'; -import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { ICustomEditorService, CONTEXT_HAS_CUSTOM_EDITORS } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -95,7 +93,8 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, { id: REOPEN_WITH_COMMAND_ID, title: REOPEN_WITH_TITLE, category: viewCategory, - } + }, + when: CONTEXT_HAS_CUSTOM_EDITORS, }); // #endregion diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 0edbf4912e0..19677c10188 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -5,7 +5,7 @@ import { coalesce, distinct } from 'vs/base/common/arrays'; import * as glob from 'vs/base/common/glob'; -import { UnownedDisposable } from 'vs/base/common/lifecycle'; +import { UnownedDisposable, Disposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { basename, DataUri, isEqual } from 'vs/base/common/resources'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -22,12 +22,13 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { EditorInput, EditorOptions, IEditor, IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { webviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint'; -import { CustomEditorPriority, CustomEditorInfo, CustomEditorSelector, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { CustomEditorPriority, CustomEditorInfo, CustomEditorSelector, ICustomEditorService, CONTEXT_HAS_CUSTOM_EDITORS } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService'; import { CustomFileEditorInput } from './customEditorInput'; +import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; const defaultEditorId = 'default'; @@ -67,18 +68,22 @@ export class CustomEditorStore { } } -export class CustomEditorService implements ICustomEditorService { +export class CustomEditorService extends Disposable implements ICustomEditorService { _serviceBrand: any; private readonly editors = new CustomEditorStore(); + private readonly _hasCustomEditor: IContextKey; constructor( + @IContextKeyService contextKeyService: IContextKeyService, @IConfigurationService private readonly configurationService: IConfigurationService, @IEditorService private readonly editorService: IEditorService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IQuickInputService private readonly quickInputService: IQuickInputService, @IWebviewService private readonly webviewService: IWebviewService, ) { + super(); + webviewEditorsExtensionPoint.setHandler(extensions => { this.editors.clear(); @@ -92,7 +97,13 @@ export class CustomEditorService implements ICustomEditorService { }); } } + this.updateContext(); }); + + this._hasCustomEditor = CONTEXT_HAS_CUSTOM_EDITORS.bindTo(contextKeyService); + + this._register(this.editorService.onDidActiveEditorChange(() => this.updateContext())); + this.updateContext(); } public getContributedCustomEditors(resource: URI): readonly CustomEditorInfo[] { @@ -154,7 +165,7 @@ export class CustomEditorService implements ICustomEditorService { resource: URI, viewType: string, group: IEditorGroup | undefined, - options?: { readonly customClasses: string }, + options?: { readonly customClasses: string; }, ): CustomFileEditorInput { const id = generateUuid(); const webview = this.webviewService.createWebviewEditorOverlay(id, { customClasses: options ? options.customClasses : undefined }, {}); @@ -190,11 +201,29 @@ export class CustomEditorService implements ICustomEditorService { } return this.editorService.openEditor(input, options, group); } + + private updateContext() { + const activeControl = this.editorService.activeControl; + if (!activeControl) { + this._hasCustomEditor.reset(); + return; + } + const resource = activeControl.input.getResource(); + if (!resource) { + this._hasCustomEditor.reset(); + return; + } + const possibleEditors = [ + ...this.getContributedCustomEditors(resource), + ...this.getUserConfiguredCustomEditors(resource), + ]; + this._hasCustomEditor.set(possibleEditors.length > 0); + } } export const customEditorsAssociationsKey = 'workbench.experimental.editorAssociations'; -export type CustomEditorsAssociations = readonly (CustomEditorSelector & { readonly viewType: string })[]; +export type CustomEditorsAssociations = readonly (CustomEditorSelector & { readonly viewType: string; })[]; export class CustomEditorContribution implements IWorkbenchContribution { constructor( diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index 699441fc7da..f635727192f 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -8,9 +8,12 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { EditorInput, IEditor } from 'vs/workbench/common/editor'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export const ICustomEditorService = createDecorator('customEditorService'); +export const CONTEXT_HAS_CUSTOM_EDITORS = new RawContextKey('hasCustomEditors', false); + export interface ICustomEditorService { _serviceBrand: any; From dad5d39eb0a251a726388f547e8dc85cd96a184d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Oct 2019 07:45:56 +0200 Subject: [PATCH 308/435] debt - cleanup main.js --- src/main.js | 181 ++++++++++++++++------------ src/vs/base/node/languagePacks.d.ts | 3 +- 2 files changed, 104 insertions(+), 80 deletions(-) diff --git a/src/main.js b/src/main.js index 4b0be14bf99..7d97a4f9343 100644 --- a/src/main.js +++ b/src/main.js @@ -25,7 +25,7 @@ const portable = bootstrap.configurePortable(); // Enable ASAR support bootstrap.enableASARSupport(); -// Set userData path before app 'ready' event and call to process.chdir +// Set userData path before app 'ready' event const args = parseCLIArgs(); const userDataPath = getUserDataPath(args); app.setPath('userData', userDataPath); @@ -37,17 +37,18 @@ setCurrentWorkingDirectory(); registerListeners(); /** - * Support user defined locale + * Support user defined locale: load it early before app('ready') + * to have more things running in parallel. * - * @type {Promise} + * @type {Promise} nlsConfig | undefined */ -let nlsConfiguration = undefined; +let nlsConfigurationPromise = undefined; const userDefinedLocale = getUserDefinedLocale(); const metaDataFile = path.join(__dirname, 'nls.metadata.json'); userDefinedLocale.then(locale => { - if (locale && !nlsConfiguration) { - nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); + if (locale && !nlsConfigurationPromise) { + nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); } }); @@ -74,62 +75,35 @@ app.once('ready', function () { } }); -function onReady() { +/** + * Main startup routine + * + * @param {string | undefined} cachedDataDir + * @param {import('./vs/base/node/languagePacks').NLSConfiguration} nlsConfig + */ +function startup(cachedDataDir, nlsConfig) { + nlsConfig._languagePackSupport = true; + + process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); + process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || ''; + + // Load main in AMD + perf.mark('willLoadMainBundle'); + require('./bootstrap-amd').load('vs/code/electron-main/main', () => { + perf.mark('didLoadMainBundle'); + }); +} + +async function onReady() { perf.mark('main:appReady'); - Promise.all([nodeCachedDataDir.ensureExists(), userDefinedLocale]).then(([cachedDataDir, locale]) => { - if (locale && !nlsConfiguration) { - nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); - } + try { + const [cachedDataDir, locale] = await Promise.all([nodeCachedDataDir.ensureExists(), userDefinedLocale]); - if (!nlsConfiguration) { - nlsConfiguration = Promise.resolve(undefined); - } - - // First, we need to test a user defined locale. If it fails we try the app locale. - // If that fails we fall back to English. - nlsConfiguration.then(nlsConfig => { - - const startup = nlsConfig => { - nlsConfig._languagePackSupport = true; - process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); - process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || ''; - - // Load main in AMD - perf.mark('willLoadMainBundle'); - require('./bootstrap-amd').load('vs/code/electron-main/main', () => { - perf.mark('didLoadMainBundle'); - }); - }; - - // We received a valid nlsConfig from a user defined locale - if (nlsConfig) { - startup(nlsConfig); - } - - // Try to use the app locale. Please note that the app locale is only - // valid after we have received the app ready event. This is why the - // code is here. - else { - let appLocale = app.getLocale(); - if (!appLocale) { - startup({ locale: 'en', availableLanguages: {} }); - } else { - - // See above the comment about the loader and case sensitiviness - appLocale = appLocale.toLowerCase(); - - lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale).then(nlsConfig => { - if (!nlsConfig) { - nlsConfig = { locale: appLocale, availableLanguages: {} }; - } - - startup(nlsConfig); - }); - } - } - }); - }, console.error); + startup(cachedDataDir, await resolveNlsConfiguration(locale)); + } catch (error) { + console.error(error); + } } /** @@ -249,7 +223,7 @@ function registerListeners() { } /** - * @returns {{ ensureExists: () => Promise }} + * @returns {{ ensureExists: () => Promise }} */ function getNodeCachedDir() { return new class { @@ -258,8 +232,14 @@ function getNodeCachedDir() { this.value = this._compute(); } - ensureExists() { - return bootstrap.mkdirp(this.value).then(() => this.value, () => { /*ignore*/ }); + async ensureExists() { + try { + await bootstrap.mkdirp(this.value); + + return this.value; + } catch (error) { + // ignore + } } _compute() { @@ -284,6 +264,50 @@ function getNodeCachedDir() { } //#region NLS Support +/** + * Resolve the NLS configuration + * + * @param {string | undefined} locale + * @return {Promise} + */ +async function resolveNlsConfiguration(locale) { + + // First, we need to test a user defined locale. If it fails we try the app locale. + // If that fails we fall back to English. + if (locale && !nlsConfigurationPromise) { + nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); + } else if (!nlsConfigurationPromise) { + nlsConfigurationPromise = Promise.resolve(undefined); + } + + // First, we need to test a user defined locale. If it fails we try the app locale. + // If that fails we fall back to English. + let nlsConfiguration = await nlsConfigurationPromise; + if (!nlsConfiguration) { + + // Try to use the app locale. Please note that the app locale is only + // valid after we have received the app ready event. This is why the + // code is here. + let appLocale = app.getLocale(); + if (!appLocale) { + nlsConfiguration = { locale: 'en', availableLanguages: {} }; + } else { + + // See above the comment about the loader and case sensitiviness + appLocale = appLocale.toLowerCase(); + + nlsConfiguration = await lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale); + if (!nlsConfiguration) { + nlsConfiguration = { locale: appLocale, availableLanguages: {} }; + } + } + } else { + // We received a valid nlsConfig from a user defined locale + } + + return nlsConfiguration; +} + /** * @param {string} content * @returns {string} @@ -312,30 +336,29 @@ function stripComments(content) { }); } -// Language tags are case insensitive however an amd loader is case sensitive -// To make this work on case preserving & insensitive FS we do the following: -// the language bundles have lower case language tags and we always lower case -// the locale we receive from the user or OS. /** + * Language tags are case insensitive however an amd loader is case sensitive + * To make this work on case preserving & insensitive FS we do the following: + * the language bundles have lower case language tags and we always lower case + * the locale we receive from the user or OS. + * * @returns {Promise} */ -function getUserDefinedLocale() { +async function getUserDefinedLocale() { const locale = args['locale']; if (locale) { - return Promise.resolve(locale.toLowerCase()); + return locale.toLowerCase(); } const localeConfig = path.join(userDataPath, 'User', 'locale.json'); - return bootstrap.readFile(localeConfig).then(content => { - content = stripComments(content); - try { - const value = JSON.parse(content).locale; - return value && typeof value === 'string' ? value.toLowerCase() : undefined; - } catch (e) { - return undefined; - } - }, () => { - return undefined; - }); + + try { + const content = stripComments(await bootstrap.readFile(localeConfig)); + + const value = JSON.parse(content).locale; + return value && typeof value === 'string' ? value.toLowerCase() : undefined; + } catch (error) { + // ignore + } } //#endregion diff --git a/src/vs/base/node/languagePacks.d.ts b/src/vs/base/node/languagePacks.d.ts index 241392e5eca..5c69043ef23 100644 --- a/src/vs/base/node/languagePacks.d.ts +++ b/src/vs/base/node/languagePacks.d.ts @@ -9,6 +9,7 @@ export interface NLSConfiguration { [key: string]: string; }; pseudo?: boolean; + _languagePackSupport?: boolean; } export interface InternalNLSConfiguration extends NLSConfiguration { @@ -20,4 +21,4 @@ export interface InternalNLSConfiguration extends NLSConfiguration { _languagePackSupport?: boolean; } -export function getNLSConfiguration(commit: string, userDataPath: string, metaDataFile: string, locale: string): Promise; \ No newline at end of file +export function getNLSConfiguration(commit: string, userDataPath: string, metaDataFile: string, locale: string): Promise; From e5b8c2f08dca126916734cafcb0bed5367df1582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 9 Oct 2019 08:14:06 +0200 Subject: [PATCH 309/435] Update listPaging.ts --- src/vs/base/browser/ui/list/listPaging.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index 420b75b9437..352dd6b8e34 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -156,7 +156,7 @@ export class PagedList implements IDisposable { } get scrollLeft(): number { - return this.list.scrollTop; + return this.list.scrollLeft; } set scrollLeft(scrollLeft: number) { From c2d3f4284f82bcc997bfc159d950f256517e3e4d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 9 Oct 2019 11:05:37 +0200 Subject: [PATCH 310/435] add overload that allows to cancel a cancellation token when calling dispose --- src/vs/base/common/cancellation.ts | 5 ++++- src/vs/base/test/common/cancellation.test.ts | 14 ++++++++++++++ src/vs/monaco.d.ts | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index fb274fb941f..f741f6b7af1 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -116,7 +116,10 @@ export class CancellationTokenSource { } } - dispose(): void { + dispose(cancel: boolean = false): void { + if (cancel) { + this.cancel(); + } if (this._parentListener) { this._parentListener.dispose(); } diff --git a/src/vs/base/test/common/cancellation.test.ts b/src/vs/base/test/common/cancellation.test.ts index 536b2e21139..88d7d26e6fb 100644 --- a/src/vs/base/test/common/cancellation.test.ts +++ b/src/vs/base/test/common/cancellation.test.ts @@ -95,6 +95,20 @@ suite('CancellationToken', function () { assert.equal(count, 0); }); + test('dispose calls no listeners (unless told to cancel)', function () { + + let count = 0; + + let source = new CancellationTokenSource(); + source.token.onCancellationRequested(function () { + count += 1; + }); + + source.dispose(true); + // source.cancel(); + assert.equal(count, 1); + }); + test('parent cancels child', function () { let parent = new CancellationTokenSource(); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 697d44580c1..0cc1100e036 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -44,7 +44,7 @@ declare namespace monaco { constructor(parent?: CancellationToken); readonly token: CancellationToken; cancel(): void; - dispose(): void; + dispose(cancel?: boolean): void; } export interface CancellationToken { From 6e52c2f1f9ba21422a2951d12ccac491cb35ee60 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 9 Oct 2019 11:07:02 +0200 Subject: [PATCH 311/435] cancel rename all the way, fixes #82146 --- src/vs/editor/contrib/rename/rename.ts | 96 +++++++++----------------- 1 file changed, 31 insertions(+), 65 deletions(-) diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index 8c0858b6984..d1267538377 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -20,15 +20,15 @@ import { Position, IPosition } from 'vs/editor/common/core/position'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { Range } from 'vs/editor/common/core/range'; import { MessageController } from 'vs/editor/contrib/message/messageController'; -import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState'; +import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/browser/core/editorState'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { URI } from 'vs/base/common/uri'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IdleValue, raceCancellation } from 'vs/base/common/async'; import { withNullAsUndefined } from 'vs/base/common/types'; class RenameSkeleton { @@ -95,7 +95,7 @@ export async function rename(model: ITextModel, position: Position, newName: str // --- register actions and commands -class RenameController extends Disposable implements IEditorContribution { +class RenameController implements IEditorContribution { private static readonly ID = 'editor.contrib.renameController'; @@ -103,13 +103,9 @@ class RenameController extends Disposable implements IEditorContribution { return editor.getContribution(RenameController.ID); } - private _renameInputField?: RenameInputField; - private _renameOperationIdPool = 1; - - private _activeRename?: { - readonly id: number; - readonly operation: CancelablePromise; - }; + private readonly _renameInputField: IdleValue; + private readonly _dispoableStore = new DisposableStore(); + private _cts: CancellationTokenSource = new CancellationTokenSource(); constructor( private readonly editor: ICodeEditor, @@ -119,37 +115,22 @@ class RenameController extends Disposable implements IEditorContribution { @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IThemeService private readonly _themeService: IThemeService, ) { - super(); - this._register(this.editor.onDidChangeModel(() => this.onModelChanged())); - this._register(this.editor.onDidChangeModelLanguage(() => this.onModelChanged())); - this._register(this.editor.onDidChangeCursorSelection(() => this.onModelChanged())); - } - - private get renameInputField(): RenameInputField { - if (!this._renameInputField) { - this._renameInputField = this._register(new RenameInputField(this.editor, this._themeService, this._contextKeyService)); - } - return this._renameInputField; + this._renameInputField = new IdleValue(() => this._dispoableStore.add(new RenameInputField(this.editor, this._themeService, this._contextKeyService))); } getId(): string { return RenameController.ID; } - async run(): Promise { - if (this._activeRename) { - this._activeRename.operation.cancel(); - } - - const id = this._renameOperationIdPool++; - this._activeRename = { - id, - operation: createCancelablePromise(token => this.doRename(token, id)) - }; - return this._activeRename.operation; + dispose(): void { + this._dispoableStore.dispose(); + this._cts.dispose(true); } - private async doRename(token: CancellationToken, id: number): Promise { + async run(): Promise { + + this._cts.dispose(true); + if (!this.editor.hasModel()) { return undefined; } @@ -161,9 +142,12 @@ class RenameController extends Disposable implements IEditorContribution { return undefined; } + this._cts = new EditorStateCancellationTokenSource(this.editor, CodeEditorStateFlag.Position | CodeEditorStateFlag.Value); + + // resolve rename location let loc: RenameLocation & Rejection | undefined; try { - const resolveLocationOperation = skeleton.resolveRenameLocation(token); + const resolveLocationOperation = skeleton.resolveRenameLocation(this._cts.token); this._progressService.showWhile(resolveLocationOperation, 250); loc = await resolveLocationOperation; } catch (e) { @@ -180,10 +164,11 @@ class RenameController extends Disposable implements IEditorContribution { return undefined; } - if (!this._activeRename || this._activeRename.id !== id) { + if (this._cts.token.isCancellationRequested) { return undefined; } + // do rename at location let selection = this.editor.getSelection(); let selectionStart = 0; let selectionEnd = loc.text.length; @@ -193,7 +178,7 @@ class RenameController extends Disposable implements IEditorContribution { selectionEnd = Math.min(loc.range.endColumn, selection.endColumn) - loc.range.startColumn; } - return this.renameInputField.getInput(loc.range, loc.text, selectionStart, selectionEnd).then(newNameOrFocusFlag => { + return this._renameInputField.getValue().getInput(loc.range, loc.text, selectionStart, selectionEnd).then(newNameOrFocusFlag => { if (typeof newNameOrFocusFlag === 'boolean') { if (newNameOrFocusFlag) { @@ -204,21 +189,15 @@ class RenameController extends Disposable implements IEditorContribution { this.editor.focus(); - const state = new EditorState(this.editor, CodeEditorStateFlag.Position | CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection | CodeEditorStateFlag.Scroll); + const renameOperation = raceCancellation(skeleton.provideRenameEdits(newNameOrFocusFlag, 0, [], this._cts.token), this._cts.token).then(result => { - const renameOperation = Promise.resolve(skeleton.provideRenameEdits(newNameOrFocusFlag, 0, [], token).then(result => { - - if (!this.editor.hasModel()) { - return undefined; + if (!result || !this.editor.hasModel()) { + return; } if (result.rejectReason) { - if (state.validate(this.editor)) { - MessageController.get(this.editor).showMessage(result.rejectReason, this.editor.getPosition()); - } else { - this._notificationService.info(result.rejectReason); - } - return undefined; + this._notificationService.info(result.rejectReason); + return; } return this._bulkEditService.apply(result, { editor: this.editor }).then(result => { @@ -231,7 +210,7 @@ class RenameController extends Disposable implements IEditorContribution { }, err => { this._notificationService.error(nls.localize('rename.failed', "Rename failed to execute.")); return Promise.reject(err); - })); + }); this._progressService.showWhile(renameOperation, 250); return renameOperation; @@ -240,24 +219,11 @@ class RenameController extends Disposable implements IEditorContribution { } public acceptRenameInput(): void { - if (this._renameInputField) { - this._renameInputField.acceptInput(); - } + this._renameInputField.getValue().acceptInput(); } public cancelRenameInput(): void { - if (this._renameInputField) { - this._renameInputField.cancelInput(true); - } - } - - private onModelChanged(): void { - if (this._activeRename) { - this._activeRename.operation.cancel(); - this._activeRename = undefined; - - this.cancelRenameInput(); - } + this._renameInputField.getValue().cancelInput(true); } } From 4885946e195f77194ab60b86671cec1515ee6b85 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 9 Oct 2019 11:10:16 +0200 Subject: [PATCH 312/435] debt - more async/await --- src/vs/editor/contrib/rename/rename.ts | 68 +++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index d1267538377..796a028890b 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -99,7 +99,7 @@ class RenameController implements IEditorContribution { private static readonly ID = 'editor.contrib.renameController'; - public static get(editor: ICodeEditor): RenameController { + static get(editor: ICodeEditor): RenameController { return editor.getContribution(RenameController.ID); } @@ -178,51 +178,51 @@ class RenameController implements IEditorContribution { selectionEnd = Math.min(loc.range.endColumn, selection.endColumn) - loc.range.startColumn; } - return this._renameInputField.getValue().getInput(loc.range, loc.text, selectionStart, selectionEnd).then(newNameOrFocusFlag => { + const newNameOrFocusFlag = await this._renameInputField.getValue().getInput(loc.range, loc.text, selectionStart, selectionEnd); - if (typeof newNameOrFocusFlag === 'boolean') { - if (newNameOrFocusFlag) { - this.editor.focus(); - } - return undefined; + + if (typeof newNameOrFocusFlag === 'boolean') { + if (newNameOrFocusFlag) { + this.editor.focus(); + } + return undefined; + } + + this.editor.focus(); + + const renameOperation = raceCancellation(skeleton.provideRenameEdits(newNameOrFocusFlag, 0, [], this._cts.token), this._cts.token).then(async renameResult => { + + if (!renameResult || !this.editor.hasModel()) { + return; } - this.editor.focus(); + if (renameResult.rejectReason) { + this._notificationService.info(renameResult.rejectReason); + return; + } - const renameOperation = raceCancellation(skeleton.provideRenameEdits(newNameOrFocusFlag, 0, [], this._cts.token), this._cts.token).then(result => { + const editResult = await this._bulkEditService.apply(renameResult, { editor: this.editor }); - if (!result || !this.editor.hasModel()) { - return; - } - - if (result.rejectReason) { - this._notificationService.info(result.rejectReason); - return; - } - - return this._bulkEditService.apply(result, { editor: this.editor }).then(result => { - // alert - if (result.ariaSummary) { - alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc!.text, newNameOrFocusFlag, result.ariaSummary)); - } - }); - - }, err => { - this._notificationService.error(nls.localize('rename.failed', "Rename failed to execute.")); - return Promise.reject(err); - }); - - this._progressService.showWhile(renameOperation, 250); - return renameOperation; + // alert + if (editResult.ariaSummary) { + alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc!.text, newNameOrFocusFlag, editResult.ariaSummary)); + } + }, err => { + this._notificationService.error(nls.localize('rename.failed', "Rename failed to execute.")); + return Promise.reject(err); }); + + this._progressService.showWhile(renameOperation, 250); + return renameOperation; + } - public acceptRenameInput(): void { + acceptRenameInput(): void { this._renameInputField.getValue().acceptInput(); } - public cancelRenameInput(): void { + cancelRenameInput(): void { this._renameInputField.getValue().cancelInput(true); } } From 861d56b788c52fa305365be1574e6f16b4af1c05 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 9 Oct 2019 12:10:06 +0200 Subject: [PATCH 313/435] fixes #82149 --- src/vs/base/common/resourceTree.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/base/common/resourceTree.ts b/src/vs/base/common/resourceTree.ts index f11e02c42b5..1272d4a6ad0 100644 --- a/src/vs/base/common/resourceTree.ts +++ b/src/vs/base/common/resourceTree.ts @@ -159,12 +159,12 @@ export class ResourceTree, C> { delete(uri: URI): T | undefined { const key = relativePath(this.root.uri, uri) || uri.fsPath; - const parts = key.split(/[\\\/]/).filter(p => !!p); - return this._delete(this.root, parts, 0); + const iterator = new PathIterator(false).reset(key); + return this._delete(this.root, iterator); } - private _delete(node: BranchNode, parts: string[], index: number): T | undefined { - const name = parts[index]; + private _delete(node: BranchNode, iterator: PathIterator): T | undefined { + const name = iterator.value(); const child = node.get(name); if (!child) { @@ -172,9 +172,9 @@ export class ResourceTree, C> { } // not at end - if (index < parts.length - 1) { + if (iterator.hasNext()) { if (child instanceof BranchNode) { - const result = this._delete(child, parts, index + 1); + const result = this._delete(child, iterator.next()); if (typeof result !== 'undefined' && child.size === 0) { node.delete(name); From 27177c51e0d49c17ea1b4186c93f89affe469247 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 9 Oct 2019 12:29:10 +0200 Subject: [PATCH 314/435] fixes #72973 --- .../contrib/scm/browser/repositoryPanel.ts | 54 +++++++++++++++++-- .../contrib/scm/browser/scm.contribution.ts | 7 ++- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index d3e83e0d735..130e661fff5 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/scmViewlet'; import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; -import { basename } from 'vs/base/common/resources'; +import { basename, isEqual } from 'vs/base/common/resources'; import { IDisposable, Disposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet'; import { append, $, addClass, toggleClass, trackFocus, removeClass } from 'vs/base/browser/dom'; @@ -32,7 +32,7 @@ import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { format } from 'vs/base/common/strings'; import { WorkbenchCompressibleObjectTree } from 'vs/platform/list/browser/listService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ThrottledDelayer } from 'vs/base/common/async'; +import { ThrottledDelayer, disposableTimeout } from 'vs/base/common/async'; import { INotificationService } from 'vs/platform/notification/common/notification'; import * as platform from 'vs/base/common/platform'; import { ITreeNode, ITreeFilter, ITreeSorter, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree'; @@ -51,6 +51,7 @@ import { flatten } from 'vs/base/common/arrays'; import { memoize } from 'vs/base/common/decorators'; import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { toResource, SideBySideEditor } from 'vs/workbench/common/editor'; type TreeElement = ISCMResourceGroup | IBranchNode | ISCMResource; @@ -409,12 +410,15 @@ class ViewModel { private items: IGroupItem[] = []; private visibilityDisposables = new DisposableStore(); private scrollTop: number | undefined; + private firstVisible = true; private disposables = new DisposableStore(); constructor( private groups: ISequence, private tree: ObjectTree, - private _mode: ViewModelMode + private _mode: ViewModelMode, + @IEditorService protected editorService: IEditorService, + @IConfigurationService protected configurationService: IConfigurationService, ) { } private onDidSpliceGroups({ start, deleteCount, toInsert }: ISplice): void { @@ -470,6 +474,9 @@ class ViewModel { this.tree.scrollTop = this.scrollTop; this.scrollTop = undefined; } + + this.editorService.onDidActiveEditorChange(this.onDidActiveEditorChange, this, this.visibilityDisposables); + this.onDidActiveEditorChange(); } else { this.visibilityDisposables.dispose(); this.onDidSpliceGroups({ start: 0, deleteCount: this.items.length, toInsert: [] }); @@ -485,6 +492,45 @@ class ViewModel { } } + private onDidActiveEditorChange(): void { + if (!this.configurationService.getValue('scm.autoReveal')) { + return; + } + + if (this.firstVisible) { + this.firstVisible = false; + this.visibilityDisposables.add(disposableTimeout(() => this.onDidActiveEditorChange(), 250)); + return; + } + + const editor = this.editorService.activeEditor; + + if (!editor) { + return; + } + + const uri = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER }); + + if (!uri) { + return; + } + + // go backwards from last group + for (let i = this.groups.elements.length - 1; i >= 0; i--) { + const group = this.groups.elements[i]; + + for (const resource of group.elements) { + if (isEqual(uri, resource.sourceUri)) { + this.tree.reveal(resource); + this.tree.setSelection([resource]); + this.tree.setFocus([resource]); + + return; + } + } + } + } + dispose(): void { this.visibilityDisposables.dispose(); this.disposables.dispose(); @@ -708,7 +754,7 @@ export class RepositoryPanel extends ViewletPanel { } } - this.viewModel = new ViewModel(this.repository.provider.groups, this.tree, mode); + this.viewModel = this.instantiationService.createInstance(ViewModel, this.repository.provider.groups, this.tree, mode); this._register(this.viewModel); addClass(this.listContainer, 'file-icon-themable-tree'); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index f1aafca78f4..64a34245284 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -115,7 +115,12 @@ Registry.as(ConfigurationExtensions.Configuration).regis ], description: localize('scm.defaultViewMode', "Controls the default Source Control repository view mode."), default: 'list' - } + }, + 'scm.autoReveal': { + type: 'boolean', + description: localize('autoReveal', "Controls whether the SCM view should automatically reveal and select files when opening them."), + default: true + }, } }); From ecea71432fb5b10172cdceb5b949cbc254bee2c1 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 9 Oct 2019 12:36:52 +0200 Subject: [PATCH 315/435] fixes #73613 --- extensions/git/src/commands.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index fdef8f17989..40141bae166 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1249,11 +1249,13 @@ export class CommandCenter { promptToSaveFilesBeforeCommit = 'never'; } + const enableSmartCommit = config.get('enableSmartCommit') === true; + if (promptToSaveFilesBeforeCommit !== 'never') { let documents = workspace.textDocuments .filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath)); - if (promptToSaveFilesBeforeCommit === 'staged') { + if (promptToSaveFilesBeforeCommit === 'staged' || repository.indexGroup.resourceStates.length > 0) { documents = documents .filter(d => repository.indexGroup.resourceStates.some(s => s.resourceUri.path === d.uri.fsPath)); } @@ -1275,7 +1277,6 @@ export class CommandCenter { } } - const enableSmartCommit = config.get('enableSmartCommit') === true; const enableCommitSigning = config.get('enableCommitSigning') === true; const noStagedChanges = repository.indexGroup.resourceStates.length === 0; const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0; From d1be9d02cd07cfc974a93ddf258ba344125d40dc Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 9 Oct 2019 12:48:21 +0200 Subject: [PATCH 316/435] :lipstick: --- extensions/git/src/commands.ts | 8 +++++--- extensions/git/src/repository.ts | 32 ++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 49ba5956cd0..349435d7aeb 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -5,7 +5,7 @@ import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, MessageOptions, WorkspaceFolder } from 'vscode'; import { Git, CommitOptions, Stash, ForcePushMode } from './git'; -import { Repository, Resource, ResourceGroupType, getBranchName } from './repository'; +import { Repository, Resource, ResourceGroupType } from './repository'; import { Model } from './model'; import { toGitUri, fromGitUri } from './uri'; import { grep, isDescendant, pathEquals } from './util'; @@ -1371,13 +1371,15 @@ export class CommandCenter { value = (await repository.getCommit(repository.HEAD.commit)).message; } - let placeHolder; - const branchName = getBranchName(repository.HEAD, repository.refs); + const branchName = repository.headShortName; + let placeHolder: string; + if (branchName) { placeHolder = localize('commitMessageWithHeadLabel2', "Message (commit on '{0}')", branchName); } else { placeHolder = localize('commit message', "Commit message"); } + return await window.showInputBox({ value, placeHolder, diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 851be585b41..416e98ce79a 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -579,6 +579,23 @@ export class Repository implements Disposable { return this._refs; } + get headShortName(): string | undefined { + if (!this.HEAD) { + return; + } + + const HEAD = this.HEAD; + const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; + const tagName = tag && tag.name; + const branchName = HEAD.name || tagName || HEAD.commit; + + if (branchName === undefined) { + return; + } + + return branchName.substr(0, 8); + } + private _remotes: Remote[] = []; get remotes(): Remote[] { return this._remotes; @@ -1643,7 +1660,7 @@ export class Repository implements Disposable { } private updateInputBoxPlaceholder(): void { - const branchName = getBranchName(this.HEAD, this.refs); + const branchName = this.headShortName; if (branchName) { // '{0}' will be replaced by the corresponding key-command later in the process, which is why it needs to stay. @@ -1657,16 +1674,3 @@ export class Repository implements Disposable { this.disposables = dispose(this.disposables); } } - -export function getBranchName(HEAD: Repository['HEAD'], refs: Repository['refs']): string | undefined { - if (HEAD === undefined) { - return; - } - const tag = refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0]; - const tagName = tag && tag.name; - const branchName = HEAD.name || tagName || HEAD.commit; - if (branchName === undefined) { - return; - } - return branchName.substr(0, 8); -} From 3831ba8c0a051f4af24b4706e7f1ac05223bb702 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Oct 2019 15:23:06 +0200 Subject: [PATCH 317/435] :up: distro --- package.json | 2 +- src/vs/code/browser/workbench/workbench-dev.html | 2 +- src/vs/code/browser/workbench/workbench.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 54f2ca80a16..8214022fe08 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "308af76bb026217c70081d07b44af5cd640c6f8b", + "distro": "dc8f3dc33797f36f9e2c695061531642de54de85", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index b59b7a2b49b..9da104d797f 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -25,7 +25,7 @@ "> - + diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index f3caa5350bf..01e0e6c909f 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -25,7 +25,7 @@ "> - + From 710be19dbfb4ec5d008bcb7884a72c7359f3fa35 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Oct 2019 15:24:43 +0200 Subject: [PATCH 318/435] Revert ":up: distro" This reverts commit 3831ba8c0a051f4af24b4706e7f1ac05223bb702. --- package.json | 2 +- src/vs/code/browser/workbench/workbench-dev.html | 2 +- src/vs/code/browser/workbench/workbench.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8214022fe08..54f2ca80a16 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "dc8f3dc33797f36f9e2c695061531642de54de85", + "distro": "308af76bb026217c70081d07b44af5cd640c6f8b", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 9da104d797f..b59b7a2b49b 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -25,7 +25,7 @@ "> - + diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index 01e0e6c909f..f3caa5350bf 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -25,7 +25,7 @@ "> - + From 2990a8f4d00cbe4ac0bcae6b7000f30bb7280920 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Oct 2019 15:25:43 +0200 Subject: [PATCH 319/435] :up: distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54f2ca80a16..7f469d57bb0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "308af76bb026217c70081d07b44af5cd640c6f8b", + "distro": "9627858bf882fef220a55f51257dca1491763dc1", "author": { "name": "Microsoft Corporation" }, From 13d3f414176e6e8dbed6cd289dfb8f726843f895 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 9 Oct 2019 16:17:31 +0200 Subject: [PATCH 320/435] [html] Format code of type="text/babel" scripts in html files. Fixes #39866 --- .../server/src/modes/embeddedSupport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/html-language-features/server/src/modes/embeddedSupport.ts b/extensions/html-language-features/server/src/modes/embeddedSupport.ts index de80fa5c8e3..df47be3ed97 100644 --- a/extensions/html-language-features/server/src/modes/embeddedSupport.ts +++ b/extensions/html-language-features/server/src/modes/embeddedSupport.ts @@ -56,7 +56,7 @@ export function getDocumentRegions(languageService: LanguageService, document: T } importedScripts.push(value); } else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') { - if (/["'](module|(text|application)\/(java|ecma)script)["']/.test(scanner.getTokenText())) { + if (/["'](module|(text|application)\/(java|ecma)script|text\/babel)["']/.test(scanner.getTokenText())) { languageIdFromType = 'javascript'; } else { languageIdFromType = undefined; @@ -228,4 +228,4 @@ function getAttributeLanguage(attributeName: string): string | null { return null; } return match[1] ? 'css' : 'javascript'; -} \ No newline at end of file +} From 65dd040a65748af2184ddddce95611276be22606 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 9 Oct 2019 07:34:22 -0700 Subject: [PATCH 321/435] Remove minimum terminal split width guard Several people complained, removing it aligns with how 'overflow' in the editor works. Fixes #72649 --- src/vs/workbench/contrib/terminal/browser/terminal.ts | 2 +- .../contrib/terminal/browser/terminalService.ts | 9 --------- src/vs/workbench/contrib/terminal/browser/terminalTab.ts | 8 ++------ 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 25baad14130..ca11750961b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -65,7 +65,7 @@ export interface ITerminalTab { setVisible(visible: boolean): void; layout(width: number, height: number): void; addDisposable(disposable: IDisposable): void; - split(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance | undefined; + split(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance; } export interface ITerminalService { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 6bb7530ed79..95b9d7de3a6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -394,11 +394,6 @@ export class TerminalService implements ITerminalService { } const instance = tab.split(this._terminalFocusContextKey, this.configHelper, shellLaunchConfig); - if (!instance) { - this._showNotEnoughSpaceToast(); - return null; - } - this._initInstanceListeners(instance); this._onInstancesChanged.fire(); @@ -495,10 +490,6 @@ export class TerminalService implements ITerminalService { return !res.confirmed; } - protected _showNotEnoughSpaceToast(): void { - this._notificationService.info(nls.localize('terminal.minWidth', "Not enough space to split terminal.")); - } - protected _validateShellPaths(label: string, potentialPaths: string[]): Promise<[string, string] | null> { if (potentialPaths.length === 0) { return Promise.resolve(null); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts index 3d4d50cdc9f..7b07a8def12 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts @@ -14,7 +14,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITerminalInstance, Direction, ITerminalTab, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; const SPLIT_PANE_MIN_SIZE = 120; -const TERMINAL_MIN_USEFUL_SIZE = 250; class SplitPaneContainer extends Disposable { private _height: number; @@ -374,14 +373,11 @@ export class TerminalTab extends Disposable implements ITerminalTab { terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig - ): ITerminalInstance | undefined { + ): ITerminalInstance { if (!this._container) { throw new Error('Cannot split terminal that has not been attached'); } - const newTerminalSize = ((this._panelPosition === Position.BOTTOM ? this._container.clientWidth : this._container.clientHeight) / (this._terminalInstances.length + 1)); - if (newTerminalSize < TERMINAL_MIN_USEFUL_SIZE) { - return undefined; - } + const instance = this._terminalService.createInstance(undefined, shellLaunchConfig); this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance); this._initInstanceListeners(instance); From b853eed359b7c0bb7c544d3f591d4c93b871edfb Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 9 Oct 2019 07:37:12 -0700 Subject: [PATCH 322/435] Remove unused params --- src/vs/workbench/contrib/terminal/browser/terminal.ts | 3 +-- .../workbench/contrib/terminal/browser/terminalService.ts | 4 +--- src/vs/workbench/contrib/terminal/browser/terminalTab.ts | 6 +----- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index ca11750961b..1997bdac7ad 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -10,7 +10,6 @@ import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShe import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IProcessEnvironment, Platform } from 'vs/base/common/platform'; import { Event } from 'vs/base/common/event'; -import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IDisposable } from 'vs/base/common/lifecycle'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { URI } from 'vs/base/common/uri'; @@ -65,7 +64,7 @@ export interface ITerminalTab { setVisible(visible: boolean): void; layout(width: number, height: number): void; addDisposable(disposable: IDisposable): void; - split(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance; + split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance; } export interface ITerminalService { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 95b9d7de3a6..173957233b9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -11,7 +11,6 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService } from 'vs/platform/notification/common/notification'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -92,7 +91,6 @@ export class TerminalService implements ITerminalService { @IPanelService private _panelService: IPanelService, @IWorkbenchLayoutService private _layoutService: IWorkbenchLayoutService, @ILifecycleService lifecycleService: ILifecycleService, - @INotificationService private _notificationService: INotificationService, @IDialogService private _dialogService: IDialogService, @IInstantiationService private _instantiationService: IInstantiationService, @IExtensionService private _extensionService: IExtensionService, @@ -393,7 +391,7 @@ export class TerminalService implements ITerminalService { return null; } - const instance = tab.split(this._terminalFocusContextKey, this.configHelper, shellLaunchConfig); + const instance = tab.split(shellLaunchConfig); this._initInstanceListeners(instance); this._onInstancesChanged.fire(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts index 7b07a8def12..68ff40e9135 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTab.ts @@ -369,11 +369,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { this.terminalInstances.forEach(i => i.setVisible(visible)); } - public split( - terminalFocusContextKey: IContextKey, - configHelper: ITerminalConfigHelper, - shellLaunchConfig: IShellLaunchConfig - ): ITerminalInstance { + public split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { if (!this._container) { throw new Error('Cannot split terminal that has not been attached'); } From 841d89748ade033e9aa58f8550474199f87aecae Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 9 Oct 2019 17:04:11 +0200 Subject: [PATCH 323/435] [rust] provide auto indent pattern. Fixes #51802 --- extensions/rust/language-configuration.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/rust/language-configuration.json b/extensions/rust/language-configuration.json index 6f198f44f4e..bd4cbb8d8f0 100644 --- a/extensions/rust/language-configuration.json +++ b/extensions/rust/language-configuration.json @@ -21,6 +21,10 @@ ["\"", "\""], ["'", "'"] ], + "indentationRules": { + "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", + "decreaseIndentPattern": "^\\s*(\\s*\\/[*].*[*]\\/\\s*)*[})]" + }, "folding": { "markers": { "start": "^\\s*//\\s*#?region\\b", From b73f9ec854ba453a2388d97dcb7ced5b0504d7cc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Oct 2019 17:15:01 +0200 Subject: [PATCH 324/435] Add a setting to disable gpu acceleration (fixes #15211) --- extensions/configuration-editing/package.json | 3 +- src/main.js | 89 ++++++++++++++++++- .../environment/common/environment.ts | 1 + .../environment/node/environmentService.ts | 12 ++- .../actions/developerActions.ts | 33 ++++++- .../electron-browser/desktop.contribution.ts | 3 +- .../environment/browser/environmentService.ts | 2 + 7 files changed, 134 insertions(+), 9 deletions(-) diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 601bc9c8a78..a5bdbba8c86 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -37,7 +37,8 @@ "launch.json", "tasks.json", "keybindings.json", - "extensions.json" + "extensions.json", + "argv.json" ] } ], diff --git a/src/main.js b/src/main.js index 7d97a4f9343..bac4f4ead6d 100644 --- a/src/main.js +++ b/src/main.js @@ -12,6 +12,8 @@ const lp = require('./vs/base/node/languagePacks'); perf.mark('main:started'); const path = require('path'); +const fs = require('fs'); +const os = require('os'); const bootstrap = require('./bootstrap'); const paths = require('./paths'); // @ts-ignore @@ -113,16 +115,97 @@ async function onReady() { */ function configureCommandlineSwitches(cliArgs) { - // Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791) - app.commandLine.appendSwitch('disable-color-correct-rendering'); + // Read argv config + const argvConfig = readArgvConfig(); + + // Append each flag to Electron + Object.keys(argvConfig).forEach(flag => { + const value = argvConfig[flag]; + if (value === true || value === 'true') { + if (flag === 'disable-gpu') { + app.disableHardwareAcceleration(); // needs to be called explicitly + } + + app.commandLine.appendArgument(flag); + } else { + app.commandLine.appendSwitch(flag, value); + } + }); // Support JS Flags const jsFlags = getJSFlags(cliArgs); if (jsFlags) { - app.commandLine.appendSwitch('--js-flags', jsFlags); + app.commandLine.appendSwitch('js-flags', jsFlags); } } +function readArgvConfig() { + + // Read or create the argv.json config file sync before app('ready') + const argvConfigPath = getArgvConfigPath(); + let argvConfig; + try { + argvConfig = JSON.parse(stripComments(fs.readFileSync(argvConfigPath).toString())); + } catch (error) { + if (error && error.code === 'ENOENT') { + try { + const argvConfigPathDirname = path.dirname(argvConfigPath); + if (!fs.existsSync(argvConfigPathDirname)) { + fs.mkdirSync(argvConfigPathDirname); + } + + // Create initial argv.json if not existing + fs.writeFileSync(argvConfigPath, `// This configuration file allows to pass permanent command line arguments to VSCode. +// +// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT +// +// If the command line argument does not have any values, simply assign +// it in the JSON below with a value of 'true'. Otherwise, put the value +// directly. +// +// If you see rendering issues in VSCode and have a better experience +// with software rendering, you can configure this by adding: +// +// 'disable-gpu': true +// +// NOTE: Changing this file requires a restart of VSCode. +{ + // Enabled by default by VSCode to resolve color issues in the renderer + // See https://github.com/Microsoft/vscode/issues/51791 for details + "disable-color-correct-rendering": true +}`); + } catch (error) { + console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`); + } + } else { + console.warn(`Unable to read argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`); + } + } + + // Fallback to default + if (!argvConfig) { + argvConfig = { + 'disable-color-correct-rendering': true // Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791) + }; + } + + return argvConfig; +} + +function getArgvConfigPath() { + const vscodePortable = process.env['VSCODE_PORTABLE']; + if (vscodePortable) { + return path.join(vscodePortable, 'argv.json'); + } + + let dataFolderName = product.dataFolderName; + if (process.env['VSCODE_DEV']) { + dataFolderName = `${dataFolderName}-dev`; + } + + return path.join(os.homedir(), dataFolderName, 'argv.json'); +} + /** * @param {ParsedArgs} cliArgs * @returns {string} diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index f24dd80b347..1d3a1760946 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -116,6 +116,7 @@ export interface IEnvironmentService { keybindingsResource: URI; keyboardLayoutResource: URI; localeResource: URI; + argvResource: URI; // sync resources userDataSyncLogResource: URI; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index f7d207009de..27408546a34 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -95,7 +95,6 @@ export class EnvironmentService implements IEnvironmentService { @memoize get userDataPath(): string { const vscodePortable = process.env['VSCODE_PORTABLE']; - if (vscodePortable) { return path.join(vscodePortable, 'user-data'); } @@ -143,6 +142,16 @@ export class EnvironmentService implements IEnvironmentService { @memoize get localeResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'locale.json'); } + @memoize + get argvResource(): URI { + const vscodePortable = process.env['VSCODE_PORTABLE']; + if (vscodePortable) { + return URI.file(path.join(vscodePortable, 'argv.json')); + } + + return URI.file(path.join(this.userHome, product.dataFolderName, 'argv.json')); + } + @memoize get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; } @@ -182,7 +191,6 @@ export class EnvironmentService implements IEnvironmentService { } const vscodePortable = process.env['VSCODE_PORTABLE']; - if (vscodePortable) { return path.join(vscodePortable, 'extensions'); } diff --git a/src/vs/workbench/electron-browser/actions/developerActions.ts b/src/vs/workbench/electron-browser/actions/developerActions.ts index a33bd626c5a..e4c1160ca47 100644 --- a/src/vs/workbench/electron-browser/actions/developerActions.ts +++ b/src/vs/workbench/electron-browser/actions/developerActions.ts @@ -7,13 +7,19 @@ import { Action } from 'vs/base/common/actions'; import * as nls from 'vs/nls'; import { IElectronService } from 'vs/platform/electron/node/electron'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; export class ToggleDevToolsAction extends Action { static readonly ID = 'workbench.action.toggleDevTools'; static readonly LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools"); - constructor(id: string, label: string, @IElectronService private readonly electronService: IElectronService) { + constructor( + id: string, + label: string, + @IElectronService private readonly electronService: IElectronService + ) { super(id, label); } @@ -27,7 +33,11 @@ export class ToggleSharedProcessAction extends Action { static readonly ID = 'workbench.action.toggleSharedProcess'; static readonly LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process"); - constructor(id: string, label: string, @ISharedProcessService private readonly sharedProcessService: ISharedProcessService) { + constructor( + id: string, + label: string, + @ISharedProcessService private readonly sharedProcessService: ISharedProcessService + ) { super(id, label); } @@ -35,3 +45,22 @@ export class ToggleSharedProcessAction extends Action { return this.sharedProcessService.toggleSharedProcessWindow(); } } + +export class ConfigureRuntimeArgumentsAction extends Action { + + static readonly ID = 'workbench.action.configureRuntimeArguments'; + static readonly LABEL = nls.localize('configureRuntimeArguments', "Configure Runtime Arguments"); + + constructor( + id: string, + label: string, + @IEnvironmentService private readonly environmentService: IEnvironmentService, + @IEditorService private readonly editorService: IEditorService + ) { + super(id, label); + } + + async run(): Promise { + await this.editorService.openEditor({ resource: this.environmentService.argvResource }); + } +} diff --git a/src/vs/workbench/electron-browser/desktop.contribution.ts b/src/vs/workbench/electron-browser/desktop.contribution.ts index b50b169627c..44481c27a31 100644 --- a/src/vs/workbench/electron-browser/desktop.contribution.ts +++ b/src/vs/workbench/electron-browser/desktop.contribution.ts @@ -11,7 +11,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; -import { ToggleSharedProcessAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions'; +import { ToggleSharedProcessAction, ToggleDevToolsAction, ConfigureRuntimeArgumentsAction } from 'vs/workbench/electron-browser/actions/developerActions'; import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions'; import { SaveWorkspaceAsAction, DuplicateWorkspaceInNewWindowAction } from 'vs/workbench/electron-browser/actions/workspaceActions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -98,6 +98,7 @@ import { IElectronService } from 'vs/platform/electron/node/electron'; (function registerDeveloperActions(): void { const developerCategory = nls.localize('developer', "Developer"); registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSharedProcessAction, ToggleSharedProcessAction.ID, ToggleSharedProcessAction.LABEL), 'Developer: Toggle Shared Process', developerCategory); + registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureRuntimeArgumentsAction, ConfigureRuntimeArgumentsAction.ID, ConfigureRuntimeArgumentsAction.LABEL), 'Developer: Configure Runtime Arguments', developerCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Developer: Reload With Extensions Disabled', developerCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL), 'Developer: Toggle Developer Tools', developerCategory); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 5f221e07ffc..9e75febd692 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -89,6 +89,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment this.keybindingsResource = joinPath(this.userRoamingDataHome, 'keybindings.json'); this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); this.localeResource = joinPath(this.userRoamingDataHome, 'locale.json'); + this.argvResource = joinPath(this.userRoamingDataHome, 'argv.json'); this.backupHome = joinPath(this.userRoamingDataHome, BACKUPS); this.configuration.backupWorkspaceResource = joinPath(this.backupHome, options.workspaceId); this.configuration.connectionToken = options.connectionToken || getCookieValue('vscode-tkn'); @@ -146,6 +147,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment keybindingsResource: URI; keyboardLayoutResource: URI; localeResource: URI; + argvResource: URI; settingsSyncPreviewResource: URI; userDataSyncLogResource: URI; machineSettingsHome: URI; From e1f09b528cd98116ff6ca480d4575994ee10a4e3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 9 Oct 2019 17:44:00 +0200 Subject: [PATCH 325/435] [themes] Disabling default themes results in empty label name. Fixes #56702 --- .../services/themes/browser/workbenchThemeService.ts | 2 +- .../services/themes/common/colorThemeStore.ts | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index b5e65780f81..e3368f14cc7 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -102,7 +102,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { ) { this.container = layoutService.getWorkbenchContainer(); - this.colorThemeStore = new ColorThemeStore(extensionService, ColorThemeData.createLoadedEmptyTheme(DEFAULT_THEME_ID, DEFAULT_THEME_SETTING_VALUE)); + this.colorThemeStore = new ColorThemeStore(extensionService); this.onFileIconThemeChange = new Emitter(); this.iconThemeStore = new FileIconThemeStore(extensionService); this.onColorThemeChange = new Emitter({ leakWarningThreshold: 400 }); diff --git a/src/vs/workbench/services/themes/common/colorThemeStore.ts b/src/vs/workbench/services/themes/common/colorThemeStore.ts index 272338755fc..7253ada3afd 100644 --- a/src/vs/workbench/services/themes/common/colorThemeStore.ts +++ b/src/vs/workbench/services/themes/common/colorThemeStore.ts @@ -57,8 +57,8 @@ export class ColorThemeStore { private readonly onDidChangeEmitter = new Emitter(); public readonly onDidChange: Event = this.onDidChangeEmitter.event; - constructor(@IExtensionService private readonly extensionService: IExtensionService, defaultTheme: ColorThemeData) { - this.extensionsColorThemes = [defaultTheme]; + constructor(@IExtensionService private readonly extensionService: IExtensionService) { + this.extensionsColorThemes = []; this.initialize(); } @@ -69,7 +69,7 @@ export class ColorThemeStore { for (const theme of this.extensionsColorThemes) { previousIds[theme.id] = true; } - this.extensionsColorThemes.length = 1; // remove all but the default theme + this.extensionsColorThemes.length = 0; for (let ext of extensions) { let extensionData = { extensionId: ext.description.identifier.value, @@ -114,11 +114,7 @@ export class ColorThemeStore { } let themeData = ColorThemeData.fromExtensionTheme(theme, colorThemeLocation, extensionData); - if (themeData.id === this.extensionsColorThemes[0].id) { - this.extensionsColorThemes[0] = themeData; - } else { - this.extensionsColorThemes.push(themeData); - } + this.extensionsColorThemes.push(themeData); }); } From ab0eb6de2d5fb4563385d98f302f78caa1767efd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 9 Oct 2019 17:50:12 +0200 Subject: [PATCH 326/435] Fixes #82153: Allow `editor.fontLigatures` to contain font-feature-settings --- src/vs/base/browser/fastDomNode.ts | 10 +++ .../editor/browser/config/charWidthReader.ts | 3 + src/vs/editor/browser/config/configuration.ts | 20 ++++-- .../browser/viewParts/lines/viewLine.ts | 7 +- .../editor/browser/widget/diffEditorWidget.ts | 6 +- src/vs/editor/browser/widget/diffReview.ts | 6 +- src/vs/editor/browser/widget/media/editor.css | 6 -- src/vs/editor/common/config/editorOptions.ts | 66 ++++++++++++++++--- src/vs/editor/common/config/fontInfo.ts | 18 +++-- .../test/common/mocks/testConfiguration.ts | 3 +- src/vs/monaco.d.ts | 3 +- 11 files changed, 110 insertions(+), 38 deletions(-) diff --git a/src/vs/base/browser/fastDomNode.ts b/src/vs/base/browser/fastDomNode.ts index cb121546529..6dfec19f492 100644 --- a/src/vs/base/browser/fastDomNode.ts +++ b/src/vs/base/browser/fastDomNode.ts @@ -18,6 +18,7 @@ export class FastDomNode { private _fontFamily: string; private _fontWeight: string; private _fontSize: number; + private _fontFeatureSettings: string; private _lineHeight: number; private _letterSpacing: number; private _className: string; @@ -38,6 +39,7 @@ export class FastDomNode { this._fontFamily = ''; this._fontWeight = ''; this._fontSize = -1; + this._fontFeatureSettings = ''; this._lineHeight = -1; this._letterSpacing = -100; this._className = ''; @@ -135,6 +137,14 @@ export class FastDomNode { this.domNode.style.fontSize = this._fontSize + 'px'; } + public setFontFeatureSettings(fontFeatureSettings: string): void { + if (this._fontFeatureSettings === fontFeatureSettings) { + return; + } + this._fontFeatureSettings = fontFeatureSettings; + this.domNode.style.fontFeatureSettings = this._fontFeatureSettings; + } + public setLineHeight(lineHeight: number): void { if (this._lineHeight === lineHeight) { return; diff --git a/src/vs/editor/browser/config/charWidthReader.ts b/src/vs/editor/browser/config/charWidthReader.ts index 601a8ae8ad7..21a54663412 100644 --- a/src/vs/editor/browser/config/charWidthReader.ts +++ b/src/vs/editor/browser/config/charWidthReader.ts @@ -71,6 +71,7 @@ class DomCharWidthReader { regularDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); regularDomNode.style.fontWeight = this._bareFontInfo.fontWeight; regularDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; + regularDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings; regularDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px'; regularDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px'; container.appendChild(regularDomNode); @@ -79,6 +80,7 @@ class DomCharWidthReader { boldDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); boldDomNode.style.fontWeight = 'bold'; boldDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; + boldDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings; boldDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px'; boldDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px'; container.appendChild(boldDomNode); @@ -87,6 +89,7 @@ class DomCharWidthReader { italicDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); italicDomNode.style.fontWeight = this._bareFontInfo.fontWeight; italicDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; + italicDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings; italicDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px'; italicDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px'; italicDomNode.style.fontStyle = 'italic'; diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 6f28ca355ff..471c97e1162 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform'; import { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader'; import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig'; -import { EditorOption, IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions'; +import { EditorOption, IEditorConstructionOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; import { IDimension } from 'vs/editor/common/editorCommon'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @@ -79,6 +79,7 @@ export interface ISerializedFontInfo { readonly fontFamily: string; readonly fontWeight: string; readonly fontSize: number; + fontFeatureSettings: string; readonly lineHeight: number; readonly letterSpacing: number; readonly isMonospace: boolean; @@ -151,11 +152,14 @@ class CSSBasedConfiguration extends Disposable { return this._cache.getValues().filter(item => item.isTrusted); } - public restoreFontInfo(savedFontInfo: ISerializedFontInfo[]): void { + public restoreFontInfo(savedFontInfos: ISerializedFontInfo[]): void { // Take all the saved font info and insert them in the cache without the trusted flag. // The reason for this is that a font might have been installed on the OS in the meantime. - for (let i = 0, len = savedFontInfo.length; i < len; i++) { - const fontInfo = new FontInfo(savedFontInfo[i], false); + for (let i = 0, len = savedFontInfos.length; i < len; i++) { + const savedFontInfo = savedFontInfos[i]; + // compatibility with older versions of VS Code which did not store this... + savedFontInfo.fontFeatureSettings = savedFontInfo.fontFeatureSettings || EditorFontLigatures.OFF; + const fontInfo = new FontInfo(savedFontInfo, false); this._writeToCache(fontInfo, fontInfo); } } @@ -171,6 +175,7 @@ class CSSBasedConfiguration extends Disposable { fontFamily: readConfig.fontFamily, fontWeight: readConfig.fontWeight, fontSize: readConfig.fontSize, + fontFeatureSettings: readConfig.fontFeatureSettings, lineHeight: readConfig.lineHeight, letterSpacing: readConfig.letterSpacing, isMonospace: readConfig.isMonospace, @@ -249,9 +254,9 @@ class CSSBasedConfiguration extends Disposable { const maxDigitWidth = Math.max(digit0.width, digit1.width, digit2.width, digit3.width, digit4.width, digit5.width, digit6.width, digit7.width, digit8.width, digit9.width); - let isMonospace = true; + let isMonospace = (bareFontInfo.fontFeatureSettings === EditorFontLigatures.OFF); const referenceWidth = monospace[0].width; - for (let i = 1, len = monospace.length; i < len; i++) { + for (let i = 1, len = monospace.length; isMonospace && i < len; i++) { const diff = referenceWidth - monospace[i].width; if (diff < -0.001 || diff > 0.001) { isMonospace = false; @@ -276,6 +281,7 @@ class CSSBasedConfiguration extends Disposable { fontFamily: bareFontInfo.fontFamily, fontWeight: bareFontInfo.fontWeight, fontSize: bareFontInfo.fontSize, + fontFeatureSettings: bareFontInfo.fontFeatureSettings, lineHeight: bareFontInfo.lineHeight, letterSpacing: bareFontInfo.letterSpacing, isMonospace: isMonospace, @@ -294,6 +300,7 @@ export class Configuration extends CommonEditorConfiguration { domNode.style.fontFamily = fontInfo.getMassagedFontFamily(); domNode.style.fontWeight = fontInfo.fontWeight; domNode.style.fontSize = fontInfo.fontSize + 'px'; + domNode.style.fontFeatureSettings = fontInfo.fontFeatureSettings; domNode.style.lineHeight = fontInfo.lineHeight + 'px'; domNode.style.letterSpacing = fontInfo.letterSpacing + 'px'; } @@ -302,6 +309,7 @@ export class Configuration extends CommonEditorConfiguration { domNode.setFontFamily(fontInfo.getMassagedFontFamily()); domNode.setFontWeight(fontInfo.fontWeight); domNode.setFontSize(fontInfo.fontSize); + domNode.setFontFeatureSettings(fontInfo.fontFeatureSettings); domNode.setLineHeight(fontInfo.lineHeight); domNode.setLetterSpacing(fontInfo.letterSpacing); } diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 4e0016d5fac..b3b0ac98942 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -16,7 +16,7 @@ import { CharacterMapping, ForeignElementType, RenderLineInput, renderViewLine, import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; import { HIGH_CONTRAST, ThemeType } from 'vs/platform/theme/common/themeService'; -import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { EditorOption, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; const canUseFastRenderedViewLine = (function () { if (platform.isNative) { @@ -77,7 +77,7 @@ export class ViewLineOptions { public readonly canUseHalfwidthRightwardsArrow: boolean; public readonly lineHeight: number; public readonly stopRenderingLineAfter: number; - public readonly fontLigatures: boolean; + public readonly fontLigatures: string; constructor(config: IConfiguration, themeType: ThemeType) { this.themeType = themeType; @@ -89,7 +89,6 @@ export class ViewLineOptions { this.useMonospaceOptimizations = ( fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations) - && !options.get(EditorOption.fontLigatures) ); this.canUseHalfwidthRightwardsArrow = fontInfo.canUseHalfwidthRightwardsArrow; this.lineHeight = options.get(EditorOption.lineHeight); @@ -218,7 +217,7 @@ export class ViewLine implements IVisibleLine { options.stopRenderingLineAfter, options.renderWhitespace, options.renderControlCharacters, - options.fontLigatures, + options.fontLigatures !== EditorFontLigatures.OFF, selectionsOnLine ); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index f6b8b30bb9c..d1bc2ad7820 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -20,7 +20,7 @@ import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffReview } from 'vs/editor/browser/widget/diffReview'; -import { IDiffEditorOptions, IEditorOptions, EditorLayoutInfo, IComputedEditorOptions, EditorOption, EditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IDiffEditorOptions, IEditorOptions, EditorLayoutInfo, IComputedEditorOptions, EditorOption, EditorOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; @@ -2060,7 +2060,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, originalModel.mightContainNonBasicASCII()); const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, originalModel.mightContainRTL()); const output = renderViewLine(new RenderLineInput( - (fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations) && !options.get(EditorOption.fontLigatures)), + (fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations)), fontInfo.canUseHalfwidthRightwardsArrow, lineContent, false, @@ -2074,7 +2074,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { options.get(EditorOption.stopRenderingLineAfter), options.get(EditorOption.renderWhitespace), options.get(EditorOption.renderControlCharacters), - options.get(EditorOption.fontLigatures), + options.get(EditorOption.fontLigatures) !== EditorFontLigatures.OFF, null // Send no selections, original line cannot be selected ), sb); diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index 0f71723805c..8a915a659ff 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -17,7 +17,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; -import { IComputedEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; +import { IComputedEditorOptions, EditorOption, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { Position } from 'vs/editor/common/core/position'; import { ILineChange, ScrollType } from 'vs/editor/common/editorCommon'; @@ -770,7 +770,7 @@ export class DiffReview extends Disposable { const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, model.mightContainNonBasicASCII()); const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, model.mightContainRTL()); const r = renderViewLine(new RenderLineInput( - (fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations) && !options.get(EditorOption.fontLigatures)), + (fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations)), fontInfo.canUseHalfwidthRightwardsArrow, lineContent, false, @@ -784,7 +784,7 @@ export class DiffReview extends Disposable { options.get(EditorOption.stopRenderingLineAfter), options.get(EditorOption.renderWhitespace), options.get(EditorOption.renderControlCharacters), - options.get(EditorOption.fontLigatures), + options.get(EditorOption.fontLigatures) !== EditorFontLigatures.OFF, null )); diff --git a/src/vs/editor/browser/widget/media/editor.css b/src/vs/editor/browser/widget/media/editor.css index fb9e5f5e8b8..7936ff11ad8 100644 --- a/src/vs/editor/browser/widget/media/editor.css +++ b/src/vs/editor/browser/widget/media/editor.css @@ -21,12 +21,6 @@ position: relative; overflow: visible; -webkit-text-size-adjust: 100%; - -webkit-font-feature-settings: "liga" off, "calt" off; - font-feature-settings: "liga" off, "calt" off; -} -.monaco-editor.enable-ligatures { - -webkit-font-feature-settings: "liga" on, "calt" on; - font-feature-settings: "liga" on, "calt" on; } /* -------------------- Misc -------------------- */ diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index dde4e5888c9..65134543ae7 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -178,7 +178,7 @@ export interface IEditorOptions { * Enable font ligatures. * Defaults to false. */ - fontLigatures?: boolean; + fontLigatures?: boolean | string; /** * Disable the use of `will-change` for the editor margin and lines layers. * The usage of `will-change` acts as a hint for browsers to create an extra layer. @@ -641,6 +641,9 @@ export interface IEditorOption { type PossibleKeyName0 = { [K in keyof IEditorOptions]: IEditorOptions[K] extends V | undefined ? K : never }[keyof IEditorOptions]; type PossibleKeyName = NonNullable>; +/** + * @internal + */ abstract class BaseEditorOption implements IEditorOption { public readonly id: K1; @@ -1044,7 +1047,7 @@ function _cursorStyleFromString(cursorStyle: 'line' | 'block' | 'underline' | 'l class EditorClassName extends ComputedEditorOption { constructor() { - super(EditorOption.editorClassName, [EditorOption.mouseStyle, EditorOption.fontLigatures, EditorOption.extraEditorClassName]); + super(EditorOption.editorClassName, [EditorOption.mouseStyle, EditorOption.extraEditorClassName]); } public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: string): string { @@ -1055,9 +1058,6 @@ class EditorClassName extends ComputedEditorOption //#endregion +//#region fontLigatures + +/** + * @internal + */ +export class EditorFontLigatures extends BaseEditorOption { + + public static OFF = '"liga" off, "calt" off'; + public static ON = '"liga" on, "calt" on'; + + constructor() { + super( + EditorOption.fontLigatures, 'fontLigatures', EditorFontLigatures.OFF, + { + anyOf: [ + { + type: 'boolean', + description: nls.localize('fontLigatures', "Enables/Disables font ligatures."), + }, + { + type: 'string', + description: nls.localize('fontFeatureSettings', "Explicit font-feature-settings.") + } + ], + default: false + } + ); + } + + public validate(input: any): string { + if (typeof input === 'undefined') { + return this.defaultValue; + } + if (typeof input === 'string') { + if (input === 'false') { + return EditorFontLigatures.OFF; + } + if (input === 'true') { + return EditorFontLigatures.ON; + } + return input; + } + if (Boolean(input)) { + return EditorFontLigatures.ON; + } + return EditorFontLigatures.OFF; + } +} + +//#endregion + //#region fontInfo class EditorFontInfo extends ComputedEditorOption { @@ -2910,10 +2961,7 @@ export const EditorOptions = { { description: nls.localize('fontFamily', "Controls the font family.") } )), fontInfo: register(new EditorFontInfo()), - fontLigatures: register(new EditorBooleanOption( - EditorOption.fontLigatures, 'fontLigatures', false, - { description: nls.localize('fontLigatures', "Enables/Disables font ligatures.") } - )), + fontLigatures2: register(new EditorFontLigatures()), fontSize: register(new EditorFontSize()), fontWeight: register(new EditorStringOption( EditorOption.fontWeight, 'fontWeight', EDITOR_FONT_DEFAULTS.fontWeight, diff --git a/src/vs/editor/common/config/fontInfo.ts b/src/vs/editor/common/config/fontInfo.ts index 6aa495b1d82..16719602fa1 100644 --- a/src/vs/editor/common/config/fontInfo.ts +++ b/src/vs/editor/common/config/fontInfo.ts @@ -28,27 +28,29 @@ export class BareFontInfo { const fontFamily = options.get(EditorOption.fontFamily); const fontWeight = options.get(EditorOption.fontWeight); const fontSize = options.get(EditorOption.fontSize); + const fontFeatureSettings = options.get(EditorOption.fontLigatures); const lineHeight = options.get(EditorOption.lineHeight); const letterSpacing = options.get(EditorOption.letterSpacing); - return BareFontInfo._create(fontFamily, fontWeight, fontSize, lineHeight, letterSpacing, zoomLevel, ignoreEditorZoom); + return BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, lineHeight, letterSpacing, zoomLevel, ignoreEditorZoom); } /** * @internal */ - public static createFromRawSettings(opts: { fontFamily?: string; fontWeight?: string; fontSize?: number; lineHeight?: number; letterSpacing?: number; }, zoomLevel: number, ignoreEditorZoom: boolean = false): BareFontInfo { + public static createFromRawSettings(opts: { fontFamily?: string; fontWeight?: string; fontSize?: number; fontLigatures?: boolean | string; lineHeight?: number; letterSpacing?: number; }, zoomLevel: number, ignoreEditorZoom: boolean = false): BareFontInfo { const fontFamily = EditorOptions.fontFamily.validate(opts.fontFamily); const fontWeight = EditorOptions.fontWeight.validate(opts.fontWeight); const fontSize = EditorOptions.fontSize.validate(opts.fontSize); + const fontFeatureSettings = EditorOptions.fontLigatures2.validate(opts.fontLigatures); const lineHeight = EditorOptions.lineHeight.validate(opts.lineHeight); const letterSpacing = EditorOptions.letterSpacing.validate(opts.letterSpacing); - return BareFontInfo._create(fontFamily, fontWeight, fontSize, lineHeight, letterSpacing, zoomLevel, ignoreEditorZoom); + return BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, lineHeight, letterSpacing, zoomLevel, ignoreEditorZoom); } /** * @internal */ - private static _create(fontFamily: string, fontWeight: string, fontSize: number, lineHeight: number, letterSpacing: number, zoomLevel: number, ignoreEditorZoom: boolean): BareFontInfo { + private static _create(fontFamily: string, fontWeight: string, fontSize: number, fontFeatureSettings: string, lineHeight: number, letterSpacing: number, zoomLevel: number, ignoreEditorZoom: boolean): BareFontInfo { if (lineHeight === 0) { lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize); } else if (lineHeight < MINIMUM_LINE_HEIGHT) { @@ -64,6 +66,7 @@ export class BareFontInfo { fontFamily: fontFamily, fontWeight: fontWeight, fontSize: fontSize, + fontFeatureSettings: fontFeatureSettings, lineHeight: lineHeight, letterSpacing: letterSpacing }); @@ -73,6 +76,7 @@ export class BareFontInfo { readonly fontFamily: string; readonly fontWeight: string; readonly fontSize: number; + readonly fontFeatureSettings: string; readonly lineHeight: number; readonly letterSpacing: number; @@ -84,6 +88,7 @@ export class BareFontInfo { fontFamily: string; fontWeight: string; fontSize: number; + fontFeatureSettings: string; lineHeight: number; letterSpacing: number; }) { @@ -91,6 +96,7 @@ export class BareFontInfo { this.fontFamily = String(opts.fontFamily); this.fontWeight = String(opts.fontWeight); this.fontSize = opts.fontSize; + this.fontFeatureSettings = opts.fontFeatureSettings; this.lineHeight = opts.lineHeight | 0; this.letterSpacing = opts.letterSpacing; } @@ -99,7 +105,7 @@ export class BareFontInfo { * @internal */ public getId(): string { - return this.zoomLevel + '-' + this.fontFamily + '-' + this.fontWeight + '-' + this.fontSize + '-' + this.lineHeight + '-' + this.letterSpacing; + return this.zoomLevel + '-' + this.fontFamily + '-' + this.fontWeight + '-' + this.fontSize + '-' + this.fontFeatureSettings + '-' + this.lineHeight + '-' + this.letterSpacing; } /** @@ -138,6 +144,7 @@ export class FontInfo extends BareFontInfo { fontFamily: string; fontWeight: string; fontSize: number; + fontFeatureSettings: string; lineHeight: number; letterSpacing: number; isMonospace: boolean; @@ -165,6 +172,7 @@ export class FontInfo extends BareFontInfo { this.fontFamily === other.fontFamily && this.fontWeight === other.fontWeight && this.fontSize === other.fontSize + && this.fontFeatureSettings === other.fontFeatureSettings && this.lineHeight === other.lineHeight && this.letterSpacing === other.letterSpacing && this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth diff --git a/src/vs/editor/test/common/mocks/testConfiguration.ts b/src/vs/editor/test/common/mocks/testConfiguration.ts index 5da181c240d..b54f06ffc90 100644 --- a/src/vs/editor/test/common/mocks/testConfiguration.ts +++ b/src/vs/editor/test/common/mocks/testConfiguration.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; @@ -33,6 +33,7 @@ export class TestConfiguration extends CommonEditorConfiguration { fontFamily: 'mockFont', fontWeight: 'normal', fontSize: 14, + fontFeatureSettings: EditorFontLigatures.OFF, lineHeight: 19, letterSpacing: 1.5, isMonospace: true, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 0cc1100e036..70aed6e2f7d 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2581,7 +2581,7 @@ declare namespace monaco.editor { * Enable font ligatures. * Defaults to false. */ - fontLigatures?: boolean; + fontLigatures?: boolean | string; /** * Disable the use of `will-change` for the editor margin and lines layers. * The usage of `will-change` acts as a hint for browsers to create an extra layer. @@ -4124,6 +4124,7 @@ declare namespace monaco.editor { readonly fontFamily: string; readonly fontWeight: string; readonly fontSize: number; + readonly fontFeatureSettings: string; readonly lineHeight: number; readonly letterSpacing: number; } From 8e574096adf6a2c844443ffb16e893d5048f165f Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 10:32:21 -0700 Subject: [PATCH 327/435] Add color tokens for active activity bar elements --- .../parts/activitybar/activitybarActions.ts | 46 +++++++++++++++++-- .../parts/activitybar/activitybarPart.ts | 4 +- .../activitybar/media/activityaction.css | 9 +++- .../browser/parts/compositeBarActions.ts | 2 + src/vs/workbench/common/theme.ts | 16 ++++++- 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index dfb216aa75e..df09c2cb2d8 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -22,7 +22,7 @@ import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarCol import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { IActivity } from 'vs/workbench/common/activity'; -import { ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -278,6 +278,42 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { `); } + const activeBorderColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER); + if (activeBorderColor) { + collector.addRule(` + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:before { + content: ""; + position: absolute; + z-index: 1; + top: 0; + bottom: 0; + margin: auto; + left: 0; + width: 100%; + height: calc(100% - 10px); + margin-left: 1px; + border-left: 2px solid ${activeBorderColor}; + } + `); + } + + const activeBackgroundColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND); + if (activeForegroundColor) { + collector.addRule(` + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + margin: auto; + width: 100%; + height: calc(100% - 10px); + margin-left: 1px; + background-color: ${activeBackgroundColor}; + } + `); + } + // Styling with Outline color (e.g. high contrast theme) const outline = theme.getColor(activeContrastBorder); if (outline) { @@ -285,9 +321,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:before { content: ""; position: absolute; - top: 9px; - left: 9px; - height: 32px; + top: 0; + bottom: 0; + left: 0; + margin: auto; + height: calc(100% - 10px); width: 32px; } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index fc2f2bf42b8..cad5dae3c1d 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -18,7 +18,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; -import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar'; import { Dimension, addClass, removeNode } from 'vs/base/browser/dom'; @@ -275,6 +275,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { return { activeForegroundColor: theme.getColor(ACTIVITY_BAR_FOREGROUND), inactiveForegroundColor: theme.getColor(ACTIVITY_BAR_INACTIVE_FOREGROUND), + activeBorderColor: theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER), + activeBackground: theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND), badgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND), badgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND), dragAndDropBackground: theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND), diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index 72c433c9a67..32125d7a880 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -10,6 +10,8 @@ } .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-label { + position: relative; + z-index: 1; display: flex; overflow: hidden; height: 40px; @@ -23,8 +25,11 @@ .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { content: ""; position: absolute; - top: 9px; - height: 32px; + top: 0; + bottom: 0; + left: 0; + margin: auto; + height: calc(100% - 10px); width: 0; border-left: 2px solid; } diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index f59e024ded1..f032f26a799 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -110,6 +110,8 @@ export class ActivityAction extends Action { export interface ICompositeBarColors { activeBackgroundColor?: Color; inactiveBackgroundColor?: Color; + activeBorderColor?: Color; + activeBackground?: Color; activeBorderBottomColor?: Color; activeForegroundColor?: Color; inactiveForegroundColor?: Color; diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index fc41153b077..af838c53afa 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -335,8 +335,8 @@ export const ACTIVITY_BAR_FOREGROUND = registerColor('activityBar.foreground', { }, nls.localize('activityBarForeground', "Activity bar item foreground color when it is active. 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_INACTIVE_FOREGROUND = registerColor('activityBar.inactiveForeground', { - dark: transparent(ACTIVITY_BAR_FOREGROUND, 0.6), - light: transparent(ACTIVITY_BAR_FOREGROUND, 0.6), + dark: transparent(ACTIVITY_BAR_FOREGROUND, 0.4), + light: transparent(ACTIVITY_BAR_FOREGROUND, 0.4), hc: Color.white }, nls.localize('activityBarInActiveForeground', "Activity bar item foreground color when it is inactive. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); @@ -346,6 +346,18 @@ 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_ACTIVE_BORDER = registerColor('activityBar.activeBorder', { + dark: ACTIVITY_BAR_FOREGROUND, + light: ACTIVITY_BAR_FOREGROUND, + hc: ACTIVITY_BAR_FOREGROUND +}, nls.localize('activityBarActiveBorder', "Activity bar border for active items. 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_ACTIVE_BACKGROUND = registerColor('activityBar.activeBackground', { + dark: transparent(ACTIVITY_BAR_FOREGROUND, 0.1), + light: transparent(ACTIVITY_BAR_FOREGROUND, 0.1), + hc: null +}, nls.localize('activityBarActiveBorder', "Activity bar border for active items. 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), From 4e53af222f66d065bb9c2128b6dbd1e3e133d9ea Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Oct 2019 10:36:12 -0700 Subject: [PATCH 328/435] Fix #75349 --- .../browser/suggestEnabledInput/suggestEnabledInput.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts index 20d1c228439..924ad443981 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.ts @@ -290,6 +290,7 @@ function getSuggestEnabledInputOptions(ariaLabel?: string): IEditorOptions { ariaLabel: ariaLabel || '', snippetSuggestions: 'none', - suggest: { filterGraceful: false, showIcons: false } + suggest: { filterGraceful: false, showIcons: false }, + autoClosingBrackets: 'never' }; } From 588576d8ddcc43c008ab7770d0614893e07896ce Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 11:49:31 -0700 Subject: [PATCH 329/435] Fix #82123 --- src/vs/workbench/api/browser/media/test.svg | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/api/browser/media/test.svg b/src/vs/workbench/api/browser/media/test.svg index 57cd408942d..569947a033e 100644 --- a/src/vs/workbench/api/browser/media/test.svg +++ b/src/vs/workbench/api/browser/media/test.svg @@ -1,10 +1,3 @@ - - - - - - - - + + - From 21ba436c514e4c1b49c8dbd206e0dbca619d7389 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 16:56:27 -0700 Subject: [PATCH 330/435] Fix one more case of #81320 The markdown link people write may be uri encoded. We need to decode these before trying to open them --- extensions/markdown-language-features/src/features/preview.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index 13f6d792a2d..16636dd1585 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -536,7 +536,7 @@ export class MarkdownPreview extends Disposable { } private async onDidClickPreviewLink(href: string) { - let [hrefPath, fragment] = href.split('#'); + let [hrefPath, fragment] = decodeURIComponent(href).split('#'); // We perviously already resolve absolute paths. // Now make sure we handle relative file paths From 6e8ff27ea624175da47d0b02282774c58644b978 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Oct 2019 23:38:30 -0700 Subject: [PATCH 331/435] Use mustable disposables These help manage lifecycle --- src/vs/editor/contrib/hover/hover.ts | 35 +++++++++++----------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index 215ddd5844c..ac7d39b6d94 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -7,7 +7,7 @@ import 'vs/css!./hover'; import * as nls from 'vs/nls'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; @@ -34,21 +34,21 @@ export class ModesHoverController implements IEditorContribution { private readonly _toUnhook = new DisposableStore(); private readonly _didChangeConfigurationHandler: IDisposable; - private _contentWidget: ModesContentHoverWidget | null; - private _glyphWidget: ModesGlyphHoverWidget | null; + private readonly _contentWidget = new MutableDisposable(); + private readonly _glyphWidget = new MutableDisposable(); get contentWidget(): ModesContentHoverWidget { - if (!this._contentWidget) { + if (!this._contentWidget.value) { this._createHoverWidgets(); } - return this._contentWidget!; + return this._contentWidget.value!; } get glyphWidget(): ModesGlyphHoverWidget { - if (!this._glyphWidget) { + if (!this._glyphWidget.value) { this._createHoverWidgets(); } - return this._glyphWidget!; + return this._glyphWidget.value!; } private _isMouseDown: boolean; @@ -69,8 +69,6 @@ export class ModesHoverController implements IEditorContribution { ) { this._isMouseDown = false; this._hoverClicked = false; - this._contentWidget = null; - this._glyphWidget = null; this._hookEvents(); @@ -197,17 +195,17 @@ export class ModesHoverController implements IEditorContribution { } private _hideWidgets(): void { - if (!this._glyphWidget || !this._contentWidget || (this._isMouseDown && this._hoverClicked && this._contentWidget.isColorPickerVisible())) { + if (!this._glyphWidget.value || !this._contentWidget.value || (this._isMouseDown && this._hoverClicked && this._contentWidget.value.isColorPickerVisible())) { return; } - this._glyphWidget!.hide(); - this._contentWidget.hide(); + this._glyphWidget.value.hide(); + this._contentWidget.value.hide(); } private _createHoverWidgets() { - this._contentWidget = new ModesContentHoverWidget(this._editor, this._markerDecorationsService, this._themeService, this._keybindingService, this._modeService, this._openerService); - this._glyphWidget = new ModesGlyphHoverWidget(this._editor, this._modeService, this._openerService); + this._contentWidget.value = new ModesContentHoverWidget(this._editor, this._markerDecorationsService, this._themeService, this._keybindingService, this._modeService, this._openerService); + this._glyphWidget.value = new ModesGlyphHoverWidget(this._editor, this._modeService, this._openerService); } public showContentHover(range: Range, mode: HoverStartMode, focus: boolean): void { @@ -222,13 +220,8 @@ export class ModesHoverController implements IEditorContribution { this._unhookEvents(); this._toUnhook.dispose(); this._didChangeConfigurationHandler.dispose(); - - if (this._glyphWidget) { - this._glyphWidget.dispose(); - } - if (this._contentWidget) { - this._contentWidget.dispose(); - } + this._glyphWidget.dispose(); + this._contentWidget.dispose(); } } From 11b28d3872bddbb94d96744cfa8bb45b879bccbc Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 9 Oct 2019 13:58:40 -0700 Subject: [PATCH 332/435] Disallow reloading in issue reporter. Fixes #77171 (#82131) --- src/bootstrap-window.js | 9 +++++---- src/vs/code/electron-browser/issue/issueReporter.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 72403b1e413..3999314e9fe 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -21,7 +21,7 @@ exports.assign = function assign(destination, source) { * * @param {string[]} modulePaths * @param {(result, configuration: object) => any} resultCallback - * @param {{ forceEnableDeveloperKeybindings?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config: object) => void, beforeLoaderConfig?: (config: object, loaderConfig: object) => void, beforeRequire?: () => void }=} options + * @param {{ forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean, canModifyDOM?: (config: object) => void, beforeLoaderConfig?: (config: object, loaderConfig: object) => void, beforeRequire?: () => void }=} options */ exports.load = function (modulePaths, resultCallback, options) { @@ -58,7 +58,7 @@ exports.load = function (modulePaths, resultCallback, options) { const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath; let developerToolsUnbind; if (enableDeveloperTools || (options && options.forceEnableDeveloperKeybindings)) { - developerToolsUnbind = registerDeveloperKeybindings(); + developerToolsUnbind = registerDeveloperKeybindings(options && options.disallowReloadKeybinding); } // Correctly inherit the parent's environment @@ -159,9 +159,10 @@ function parseURLQueryArgs() { } /** + * @param {boolean} disallowReloadKeybinding * @returns {() => void} */ -function registerDeveloperKeybindings() { +function registerDeveloperKeybindings(disallowReloadKeybinding) { // @ts-ignore const ipc = require('electron').ipcRenderer; @@ -185,7 +186,7 @@ function registerDeveloperKeybindings() { const key = extractKey(e); if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) { ipc.send('vscode:toggleDevTools'); - } else if (key === RELOAD_KB) { + } else if (key === RELOAD_KB && !disallowReloadKeybinding) { ipc.send('vscode:reloadWindow'); } }; diff --git a/src/vs/code/electron-browser/issue/issueReporter.js b/src/vs/code/electron-browser/issue/issueReporter.js index 71c2b34a4e5..5d11dd15ae4 100644 --- a/src/vs/code/electron-browser/issue/issueReporter.js +++ b/src/vs/code/electron-browser/issue/issueReporter.js @@ -10,4 +10,4 @@ const bootstrapWindow = require('../../../../bootstrap-window'); bootstrapWindow.load(['vs/code/electron-browser/issue/issueReporterMain'], function (issueReporter, configuration) { issueReporter.startup(configuration); -}, { forceEnableDeveloperKeybindings: true }); \ No newline at end of file +}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true }); From 6032e84542a6358e7695aad1d889f67e0887c02a Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 9 Oct 2019 14:53:39 -0700 Subject: [PATCH 333/435] Strict property initialization errors for comments panel, #78168 --- .../browser/commentsEditorContribution.ts | 5 +---- .../contrib/comments/browser/commentsPanel.ts | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index bd3ea6d7f9d..87f2dd31cc5 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -76,10 +76,7 @@ class CommentingRangeDecoration { options: commentingOptions }]; - let model = this._editor.getModel(); - if (model) { - this._decorationId = model.deltaDecorations([this._decorationId], commentingRangeDecorations)[0]; - } + this._decorationId = this._editor.deltaDecorations([], commentingRangeDecorations)[0]; } public getCommentAction(): { ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges } { diff --git a/src/vs/workbench/contrib/comments/browser/commentsPanel.ts b/src/vs/workbench/contrib/comments/browser/commentsPanel.ts index 5f0e33758a4..eeafa5eb74a 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsPanel.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsPanel.ts @@ -27,13 +27,13 @@ import { CommentsList, COMMENTS_PANEL_ID, COMMENTS_PANEL_TITLE } from 'vs/workbe export class CommentsPanel extends Panel { - private treeLabels: ResourceLabels; - private tree: CommentsList; - private treeContainer: HTMLElement; - private messageBoxContainer: HTMLElement; - private messageBox: HTMLElement; - private commentsModel: CommentsModel; - private collapseAllAction: IAction; + private treeLabels!: ResourceLabels; + private tree!: CommentsList; + private treeContainer!: HTMLElement; + private messageBoxContainer!: HTMLElement; + private messageBox!: HTMLElement; + private commentsModel!: CommentsModel; + private collapseAllAction?: IAction; constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -195,7 +195,9 @@ export class CommentsPanel extends Panel { private refresh(): void { if (this.isVisible()) { - this.collapseAllAction.enabled = this.commentsModel.hasCommentThreads(); + if (this.collapseAllAction) { + this.collapseAllAction.enabled = this.commentsModel.hasCommentThreads(); + } dom.toggleClass(this.treeContainer, 'hidden', !this.commentsModel.hasCommentThreads()); this.tree.updateChildren().then(() => { From 7aae845a6a55f11111e4beeb80592404af73314a Mon Sep 17 00:00:00 2001 From: Greg Van Liew Date: Wed, 9 Oct 2019 15:43:19 -0700 Subject: [PATCH 334/435] Add a link to Where to Contribute Fixes #74102 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5743ba55e8d..5d39d7e40c6 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ please see the document [How to Contribute](https://github.com/Microsoft/vscode/ * [The development workflow, including debugging and running tests](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#debugging) * [Coding guidelines](https://github.com/Microsoft/vscode/wiki/Coding-Guidelines) * [Submitting pull requests](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#pull-requests) +* [Finding an issue to work on](https://github.com/microsoft/vscode/wiki/How-to-Contribute#where-to-contribute) * [Contributing to translations](https://aka.ms/vscodeloc) ## Feedback From 7a42d5a6ab09b1cc3472adb3a7ae3cc1b4265489 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Oct 2019 16:47:35 -0700 Subject: [PATCH 335/435] Fix #76862 --- src/vs/workbench/contrib/search/browser/searchView.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index d9bdee92201..326e78344bb 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -930,6 +930,8 @@ export class SearchView extends ViewletPanel { this.searchWidget.clear(); this.viewModel.cancelSearch(); this.updateActions(); + + aria.status(nls.localize('ariaSearchResultsClearStatus', "The search results have been cleared")); } cancelSearch(): boolean { From 2da0921c2ce515e39af8cc8ee21e9c42a31080bd Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Oct 2019 16:48:03 -0700 Subject: [PATCH 336/435] Fix #76203 --- src/vs/editor/test/common/core/range.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/test/common/core/range.test.ts b/src/vs/editor/test/common/core/range.test.ts index 1d2d627cb32..5420ae45223 100644 --- a/src/vs/editor/test/common/core/range.test.ts +++ b/src/vs/editor/test/common/core/range.test.ts @@ -87,9 +87,9 @@ suite('Editor Core - Range', () => { b = new Range(1, 1, 1, 4); assert.ok(Range.compareRangesUsingEnds(a, b) > 0, 'a.start = b.start, a.end > b.end'); - a = new Range(1, 1, 5, 1); + a = new Range(1, 2, 5, 1); b = new Range(1, 1, 1, 4); - assert.ok(Range.compareRangesUsingEnds(a, b) > 0, 'a.start = b.start, a.end > b.end'); + assert.ok(Range.compareRangesUsingEnds(a, b) > 0, 'a.start > b.start, a.end > b.end'); }); test('containsPosition', () => { From ecb1de1afec109f311048edeb2ce3dccf0c4c270 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 9 Oct 2019 17:26:54 -0700 Subject: [PATCH 337/435] update gdpr tag for measurement --- src/vs/platform/telemetry/node/commonProperties.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index 567bc8e9db8..d681c0c7733 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -39,7 +39,7 @@ export async function resolveCommonProperties( const msftInternal = verifyMicrosoftInternalDomain(msftInternalDomains || []); if (msftInternal) { - // __GDPR__COMMON__ "common.msftInternal" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.msftInternal" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } result['common.msftInternal'] = msftInternal; } From c0bd994bc75b2fcc2510675a8d1b34ea34f9557b Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Oct 2019 18:30:24 -0700 Subject: [PATCH 338/435] Fix PHP indentation rule for 'case' Fix #81107 --- extensions/php/language-configuration.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 2eb11e31045..a25868a4175 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -25,7 +25,7 @@ ["`", "`"] ], "indentationRules": { - "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch).*:)\\s*(/[/*].*)?$", + "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*(/[/*].*)?$", "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" }, "folding": { @@ -34,4 +34,4 @@ "end": "^\\s*(#|\/\/)endregion\\b" } } -} \ No newline at end of file +} From 193fead4103363d1a14873bcf38181d97cf611f6 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 20:03:39 -0700 Subject: [PATCH 339/435] Fix #82192 --- .../contrib/search/browser/media/searchview.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/media/searchview.css b/src/vs/workbench/contrib/search/browser/media/searchview.css index 02cc969b0d6..2ddcf6be133 100644 --- a/src/vs/workbench/contrib/search/browser/media/searchview.css +++ b/src/vs/workbench/contrib/search/browser/media/searchview.css @@ -91,8 +91,12 @@ .search-view .search-widget .replace-container .monaco-action-bar .action-item .codicon { background-repeat: no-repeat; - width: 20px; + width: 25px; height: 25px; + margin-right: 0; + display: flex; + align-items: center; + justify-content: center; } .search-view .query-details { @@ -103,10 +107,9 @@ .search-view .query-details .more { position: absolute; - margin-right: 0.3em; right: 0; cursor: pointer; - width: 16px; + width: 25px; height: 16px; z-index: 2; /* Force it above the search results message, which has a negative top margin */ } From 7dea3f12b58764d656486f4fd7418bee40a27a98 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 20:35:54 -0700 Subject: [PATCH 340/435] Use unique dom element to style active activiy bar elements --- .../parts/activitybar/activitybarActions.ts | 33 ++++-------------- .../activitybar/media/activityaction.css | 34 ++++++++++++++++--- .../browser/parts/compositeBarActions.ts | 3 ++ src/vs/workbench/common/theme.ts | 6 ++-- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index df09c2cb2d8..dbfbdf0ebc0 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -281,18 +281,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const activeBorderColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER); if (activeBorderColor) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:before { - content: ""; - position: absolute; - z-index: 1; - top: 0; - bottom: 0; - margin: auto; - left: 0; - width: 100%; - height: calc(100% - 10px); - margin-left: 1px; - border-left: 2px solid ${activeBorderColor}; + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { + border-left-color: ${activeBorderColor}; } `); } @@ -300,15 +290,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const activeBackgroundColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND); if (activeForegroundColor) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:after { - content: ""; - position: absolute; - top: 0; - bottom: 0; - margin: auto; - width: 100%; - height: calc(100% - 10px); - margin-left: 1px; + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item { + z-index: 0; background-color: ${activeBackgroundColor}; } `); @@ -321,11 +304,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:before { content: ""; position: absolute; - top: 0; - bottom: 0; - left: 0; - margin: auto; - height: calc(100% - 10px); + top: 9px; + left: 9px; + height: 32px; width: 32px; } diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index 32125d7a880..dcb58126693 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -22,32 +22,56 @@ font-size: 15px; } +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { content: ""; position: absolute; - top: 0; - bottom: 0; - left: 0; - margin: auto; - height: calc(100% - 10px); + top: 9px; + height: 32px; + z-index: 1; + top: 5px; + height: 40px; width: 0; border-left: 2px solid; } +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { + top: 0; + height: 100%; +} + +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:focus .active-item:before { + border-left: none; /* don't show active border + focus at the same time, focus takes priority */ +} + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.clicked:focus:before { border-left: none !important; /* no focus feedback when using mouse */ } +.monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, .monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { left: 1px; } +.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, .monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { right: 1px; } +.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { + right: 2px; +} + +/* Hides outline on HC as focus is handled by border */ +.hc-black .monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before, +.hc-black .monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { + outline: none; +} + +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .active-item, .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .badge { position: absolute; + z-index: 1; top: 5px; left: 0; overflow: hidden; diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index f032f26a799..1d1b95e2464 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -213,6 +213,9 @@ export class ActivityActionViewItem extends BaseActionViewItem { this.badge = dom.append(container, dom.$('.badge')); this.badgeContent = dom.append(this.badge, dom.$('.badge-content')); + // Active border + background + dom.append(container, dom.$('.active-item')); + dom.hide(this.badge); this.updateActivity(); diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index af838c53afa..ff7ed6931fa 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -349,12 +349,12 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { export const ACTIVITY_BAR_ACTIVE_BORDER = registerColor('activityBar.activeBorder', { dark: ACTIVITY_BAR_FOREGROUND, light: ACTIVITY_BAR_FOREGROUND, - hc: ACTIVITY_BAR_FOREGROUND + hc: transparent(Color.white, 0) }, nls.localize('activityBarActiveBorder', "Activity bar border for active items. 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_ACTIVE_BACKGROUND = registerColor('activityBar.activeBackground', { - dark: transparent(ACTIVITY_BAR_FOREGROUND, 0.1), - light: transparent(ACTIVITY_BAR_FOREGROUND, 0.1), + dark: null, + light: null, hc: null }, nls.localize('activityBarActiveBorder', "Activity bar border for active items. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); From 38b235b35cf3427a6e65b1405d206aa5fcba2070 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 20:45:19 -0700 Subject: [PATCH 341/435] Update description --- src/vs/workbench/common/theme.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index ff7ed6931fa..7dd36c89319 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -350,13 +350,13 @@ export const ACTIVITY_BAR_ACTIVE_BORDER = registerColor('activityBar.activeBorde dark: ACTIVITY_BAR_FOREGROUND, light: ACTIVITY_BAR_FOREGROUND, hc: transparent(Color.white, 0) -}, nls.localize('activityBarActiveBorder', "Activity bar border for active items. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +}, nls.localize('activityBarActiveBorder', "Activity bar border color for the active item. 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_ACTIVE_BACKGROUND = registerColor('activityBar.activeBackground', { dark: null, light: null, hc: null -}, nls.localize('activityBarActiveBorder', "Activity bar border for active items. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +}, nls.localize('activityBarActiveBackground', "Activity bar background color for the active item. 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), From 5943d065e3b2b4f35ab527411312af79e19c926b Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 20:54:36 -0700 Subject: [PATCH 342/435] Hide active elements in HC mode --- .../browser/parts/activitybar/media/activityaction.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index dcb58126693..2742a7e438c 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -44,6 +44,11 @@ border-left: none; /* don't show active border + focus at the same time, focus takes priority */ } +/* Hides active elements in high contrast mode */ +.hc-black .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item { + display: none; +} + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.clicked:focus:before { border-left: none !important; /* no focus feedback when using mouse */ } From 0575dd40d9b6809a08b3cc1b8f5f9ce394c0880c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 07:37:06 +0200 Subject: [PATCH 343/435] improve static argv configuration (#15211) --- extensions/configuration-editing/package.json | 4 +- src/main.js | 188 +++++++++++------- .../environment/common/environment.ts | 1 - src/vs/platform/environment/node/argv.ts | 1 - .../environment/node/environmentService.ts | 3 - .../browser/localizations.contribution.ts | 46 +---- .../browser/localizationsActions.ts | 2 +- .../electron-browser/desktop.contribution.ts | 30 +++ .../environment/browser/environmentService.ts | 2 - .../textfile/common/textFileEditorModel.ts | 5 - 10 files changed, 151 insertions(+), 131 deletions(-) diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index a5bdbba8c86..bd10c038f8a 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -72,8 +72,8 @@ "url": "vscode://schemas/workspaceConfig" }, { - "fileMatch": "%APP_SETTINGS_HOME%/locale.json", - "url": "vscode://schemas/locale" + "fileMatch": "**/argv.json", + "url": "vscode://schemas/argv" }, { "fileMatch": "/.vscode/settings.json", diff --git a/src/main.js b/src/main.js index bac4f4ead6d..a96b411bf8b 100644 --- a/src/main.js +++ b/src/main.js @@ -38,6 +38,12 @@ setCurrentWorkingDirectory(); // Global app listeners registerListeners(); +// Cached data +const nodeCachedDataDir = getNodeCachedDir(); + +// Configure static command line arguments +const argvConfig = configureCommandlineSwitchesSync(args); + /** * Support user defined locale: load it early before app('ready') * to have more things running in parallel. @@ -45,20 +51,12 @@ registerListeners(); * @type {Promise} nlsConfig | undefined */ let nlsConfigurationPromise = undefined; -const userDefinedLocale = getUserDefinedLocale(); + const metaDataFile = path.join(__dirname, 'nls.metadata.json'); - -userDefinedLocale.then(locale => { - if (locale && !nlsConfigurationPromise) { - nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); - } -}); - -// Cached data -const nodeCachedDataDir = getNodeCachedDir(); - -// Configure command line switches -configureCommandlineSwitches(args); +const locale = getUserDefinedLocale(argvConfig); +if (locale) { + nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); +} // Load our code once ready app.once('ready', function () { @@ -100,9 +98,9 @@ async function onReady() { perf.mark('main:appReady'); try { - const [cachedDataDir, locale] = await Promise.all([nodeCachedDataDir.ensureExists(), userDefinedLocale]); + const [cachedDataDir, nlsConfig] = await Promise.all([nodeCachedDataDir.ensureExists(), resolveNlsConfiguration()]); - startup(cachedDataDir, await resolveNlsConfiguration(locale)); + startup(cachedDataDir, nlsConfig); } catch (error) { console.error(error); } @@ -113,22 +111,34 @@ async function onReady() { * * @param {ParsedArgs} cliArgs */ -function configureCommandlineSwitches(cliArgs) { +function configureCommandlineSwitchesSync(cliArgs) { + const SUPPORTED_ELECTRON_SWITCHES = [ + + // alias from us for --disable-gpu + 'disable-hardware-acceleration', + + // provided by Electron + 'disable-color-correct-rendering' + ]; // Read argv config - const argvConfig = readArgvConfig(); + const argvConfig = readArgvConfigSync(); // Append each flag to Electron - Object.keys(argvConfig).forEach(flag => { - const value = argvConfig[flag]; - if (value === true || value === 'true') { - if (flag === 'disable-gpu') { - app.disableHardwareAcceleration(); // needs to be called explicitly - } + Object.keys(argvConfig).forEach(argvKey => { + if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) === -1) { + return; // unsupported argv key + } - app.commandLine.appendArgument(flag); + const argvValue = argvConfig[argvKey]; + if (argvValue === true || argvValue === 'true') { + if (argvKey === 'disable-hardware-acceleration') { + app.disableHardwareAcceleration(); // needs to be called explicitly + } else { + app.commandLine.appendArgument(argvKey); + } } else { - app.commandLine.appendSwitch(flag, value); + app.commandLine.appendSwitch(argvKey, argvValue); } }); @@ -137,9 +147,11 @@ function configureCommandlineSwitches(cliArgs) { if (jsFlags) { app.commandLine.appendSwitch('js-flags', jsFlags); } + + return argvConfig; } -function readArgvConfig() { +function readArgvConfigSync() { // Read or create the argv.json config file sync before app('ready') const argvConfigPath = getArgvConfigPath(); @@ -148,35 +160,7 @@ function readArgvConfig() { argvConfig = JSON.parse(stripComments(fs.readFileSync(argvConfigPath).toString())); } catch (error) { if (error && error.code === 'ENOENT') { - try { - const argvConfigPathDirname = path.dirname(argvConfigPath); - if (!fs.existsSync(argvConfigPathDirname)) { - fs.mkdirSync(argvConfigPathDirname); - } - - // Create initial argv.json if not existing - fs.writeFileSync(argvConfigPath, `// This configuration file allows to pass permanent command line arguments to VSCode. -// -// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT -// -// If the command line argument does not have any values, simply assign -// it in the JSON below with a value of 'true'. Otherwise, put the value -// directly. -// -// If you see rendering issues in VSCode and have a better experience -// with software rendering, you can configure this by adding: -// -// 'disable-gpu': true -// -// NOTE: Changing this file requires a restart of VSCode. -{ - // Enabled by default by VSCode to resolve color issues in the renderer - // See https://github.com/Microsoft/vscode/issues/51791 for details - "disable-color-correct-rendering": true -}`); - } catch (error) { - console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`); - } + createDefaultArgvConfigSync(argvConfigPath); } else { console.warn(`Unable to read argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`); } @@ -192,6 +176,70 @@ function readArgvConfig() { return argvConfig; } +/** + * @param {string} argvConfigPath + */ +function createDefaultArgvConfigSync(argvConfigPath) { + try { + + // Ensure argv config parent exists + const argvConfigPathDirname = path.dirname(argvConfigPath); + if (!fs.existsSync(argvConfigPathDirname)) { + fs.mkdirSync(argvConfigPathDirname); + } + + // Migrate over legacy locale + const localeConfigPath = path.join(userDataPath, 'User', 'locale.json'); + const legacyLocale = getLegacyUserDefinedLocaleSync(localeConfigPath); + if (legacyLocale) { + try { + fs.unlinkSync(localeConfigPath); + } catch (error) { + //ignore + } + } + + // Default argv content + const defaultArgvConfigContent = [ + '// This configuration file allows to pass permanent command line arguments to VSCode.', + '// Only a subset of arguments is currently supported to reduce the likelyhood of breaking', + '// the installation.', + '//', + '// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT', + '//', + '// If the command line argument does not have any values, simply assign', + '// it in the JSON below with a value of \'true\'. Otherwise, put the value', + '// directly.', + '//', + '// If you see rendering issues in VSCode and have a better experience', + '// with software rendering, you can configure this by adding:', + '//', + '// \'disable-hardware-acceleration\': true', + '//', + '// NOTE: Changing this file requires a restart of VSCode.', + '{', + ' // Enabled by default by VSCode to resolve color issues in the renderer', + ' // See https://github.com/Microsoft/vscode/issues/51791 for details', + ' "disable-color-correct-rendering": true' + ]; + + if (legacyLocale) { + defaultArgvConfigContent[defaultArgvConfigContent.length - 1] = `${defaultArgvConfigContent[defaultArgvConfigContent.length - 1]},`; // append trailing "," + + defaultArgvConfigContent.push(''); + defaultArgvConfigContent.push(' // Display language of VSCode'); + defaultArgvConfigContent.push(` "locale": "${legacyLocale}"`); + } + + defaultArgvConfigContent.push('}'); + + // Create initial argv.json with default content + fs.writeFileSync(argvConfigPath, defaultArgvConfigContent.join('\n')); + } catch (error) { + console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`); + } +} + function getArgvConfigPath() { const vscodePortable = process.env['VSCODE_PORTABLE']; if (vscodePortable) { @@ -350,22 +398,13 @@ function getNodeCachedDir() { /** * Resolve the NLS configuration * - * @param {string | undefined} locale * @return {Promise} */ -async function resolveNlsConfiguration(locale) { +async function resolveNlsConfiguration() { // First, we need to test a user defined locale. If it fails we try the app locale. // If that fails we fall back to English. - if (locale && !nlsConfigurationPromise) { - nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); - } else if (!nlsConfigurationPromise) { - nlsConfigurationPromise = Promise.resolve(undefined); - } - - // First, we need to test a user defined locale. If it fails we try the app locale. - // If that fails we fall back to English. - let nlsConfiguration = await nlsConfigurationPromise; + let nlsConfiguration = nlsConfigurationPromise ? await nlsConfigurationPromise : undefined; if (!nlsConfiguration) { // Try to use the app locale. Please note that the app locale is only @@ -425,18 +464,25 @@ function stripComments(content) { * the language bundles have lower case language tags and we always lower case * the locale we receive from the user or OS. * - * @returns {Promise} + * @param {{ locale: string | undefined; }} argvConfig + * @returns {string | undefined} */ -async function getUserDefinedLocale() { +function getUserDefinedLocale(argvConfig) { const locale = args['locale']; if (locale) { - return locale.toLowerCase(); + return locale.toLowerCase(); // a directly provided --locale always wins } - const localeConfig = path.join(userDataPath, 'User', 'locale.json'); + return argvConfig.locale && typeof argvConfig.locale === 'string' ? argvConfig.locale.toLowerCase() : undefined; +} +/** + * @param {string} localeConfigPath + * @returns {string | undefined} + */ +function getLegacyUserDefinedLocaleSync(localeConfigPath) { try { - const content = stripComments(await bootstrap.readFile(localeConfig)); + const content = stripComments(fs.readFileSync(localeConfigPath).toString()); const value = JSON.parse(content).locale; return value && typeof value === 'string' ? value.toLowerCase() : undefined; diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 1d3a1760946..99a9753a4df 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -115,7 +115,6 @@ export interface IEnvironmentService { settingsResource: URI; keybindingsResource: URI; keyboardLayoutResource: URI; - localeResource: URI; argvResource: URI; // sync resources diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index c15320d20b1..5b49fd0dd46 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -303,7 +303,6 @@ export function buildVersionMessage(version: string | undefined, commit: string return `${version || localize('unknownVersion', "Unknown version")}\n${commit || localize('unknownCommit', "Unknown commit")}\n${process.arch}`; } - export function addArg(argv: string[], ...args: string[]): string[] { const endOfArgsMarkerIndex = argv.indexOf('--'); if (endOfArgsMarkerIndex === -1) { diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 27408546a34..5c2b8296750 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -139,9 +139,6 @@ export class EnvironmentService implements IEnvironmentService { @memoize get keyboardLayoutResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); } - @memoize - get localeResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'locale.json'); } - @memoize get argvResource(): URI { const vscodePortable = process.env['VSCODE_PORTABLE']; diff --git a/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts b/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts index d96fb5eee92..06b20c612ce 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts @@ -6,13 +6,11 @@ import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { Disposable } from 'vs/base/common/lifecycle'; import { ConfigureLocaleAction } from 'vs/workbench/contrib/localizations/browser/localizationsActions'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { IExtensionManagementService, DidInstallExtensionEvent, IExtensionGalleryService, IGalleryExtension, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -35,7 +33,6 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, export class LocalizationWorkbenchContribution extends Disposable implements IWorkbenchContribution { constructor( - @ILocalizationsService private readonly localizationService: ILocalizationsService, @INotificationService private readonly notificationService: INotificationService, @IJSONEditingService private readonly jsonEditingService: IJSONEditingService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @@ -47,26 +44,10 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo @ITelemetryService private readonly telemetryService: ITelemetryService ) { super(); - this.updateLocaleDefintionSchema(); this.checkAndInstall(); - this._register(this.localizationService.onDidLanguagesChange(() => this.updateLocaleDefintionSchema())); this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e))); } - private updateLocaleDefintionSchema(): void { - this.localizationService.getLanguageIds() - .then(languageIds => { - let lowercaseLanguageIds: string[] = []; - languageIds.forEach((languageId) => { - let lowercaseLanguageId = languageId.toLowerCase(); - if (lowercaseLanguageId !== languageId) { - lowercaseLanguageIds.push(lowercaseLanguageId); - } - }); - registerLocaleDefinitionSchema([...languageIds, ...lowercaseLanguageIds]); - }); - } - private onDidInstallExtension(e: DidInstallExtensionEvent): void { if (e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) { const locale = e.local.manifest.contributes.localizations[0].languageId; @@ -79,7 +60,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo [{ label: updateAndRestart ? localize('yes', "Yes") : localize('restart now', "Restart Now"), run: () => { - const updatePromise = updateAndRestart ? this.jsonEditingService.write(this.environmentService.localeResource, [{ key: 'locale', value: locale }], true) : Promise.resolve(undefined); + const updatePromise = updateAndRestart ? this.jsonEditingService.write(this.environmentService.argvResource, [{ key: 'locale', value: locale }], true) : Promise.resolve(undefined); updatePromise.then(() => this.hostService.restart(), e => this.notificationService.error(e)); } }], @@ -225,31 +206,6 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo } } -function registerLocaleDefinitionSchema(languages: string[]): void { - const localeDefinitionFileSchemaId = 'vscode://schemas/locale'; - const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); - // Keep en-US since we generated files with that content. - jsonRegistry.registerSchema(localeDefinitionFileSchemaId, { - id: localeDefinitionFileSchemaId, - allowComments: true, - allowTrailingCommas: true, - description: 'Locale Definition file', - type: 'object', - default: { - 'locale': 'en' - }, - required: ['locale'], - properties: { - locale: { - type: 'string', - enum: languages, - description: localize('JsonSchema.locale', 'The UI Language to use.') - } - } - }); -} - -registerLocaleDefinitionSchema(platform.language ? [platform.language] : []); const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(LocalizationWorkbenchContribution, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts index cd04dd6149c..b7b2a9030e6 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts @@ -65,7 +65,7 @@ export class ConfigureLocaleAction extends Action { } if (selectedLanguage) { - await this.jsonEditingService.write(this.environmentService.localeResource, [{ key: 'locale', value: selectedLanguage.label }], true); + await this.jsonEditingService.write(this.environmentService.argvResource, [{ key: 'locale', value: selectedLanguage.label }], true); const restart = await this.dialogService.confirm({ type: 'info', message: localize('relaunchDisplayLanguageMessage', "A restart is required for the change in display language to take effect."), diff --git a/src/vs/workbench/electron-browser/desktop.contribution.ts b/src/vs/workbench/electron-browser/desktop.contribution.ts index 44481c27a31..542252803db 100644 --- a/src/vs/workbench/electron-browser/desktop.contribution.ts +++ b/src/vs/workbench/electron-browser/desktop.contribution.ts @@ -21,6 +21,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext } from 'vs/workbench/browser/contextkeys'; import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor'; import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; // Actions (function registerActions(): void { @@ -342,3 +343,32 @@ import { IElectronService } from 'vs/platform/electron/node/electron'; } }); })(); + +// JSON Schemas +(function registerJSONSchemas(): void { + const argvDefinitionFileSchemaId = 'vscode://schemas/argv'; + const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); + + jsonRegistry.registerSchema(argvDefinitionFileSchemaId, { + id: argvDefinitionFileSchemaId, + allowComments: true, + allowTrailingCommas: true, + description: 'VSCode static command line definition file', + type: 'object', + additionalProperties: false, + properties: { + locale: { + type: 'string', + description: nls.localize('argv.locale', 'The display Language to use. Picking a different language requires the associated language pack to be installed.') + }, + 'disable-hardware-acceleration': { + type: 'boolean', + description: nls.localize('argv.disableHardwareAcceleration', 'Disables hardware acceleration. ONLY change this option if you encounter graphic issues.') + }, + 'disable-color-correct-rendering': { + type: 'boolean', + description: nls.localize('argv.disableColorCorrectRendering', 'Resolves issues around color profile selection. ONLY change this option if you encounter graphic issues.') + } + } + }); +})(); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 9e75febd692..b85732fef57 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -88,7 +88,6 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment this.userDataSyncLogResource = joinPath(options.logsPath, 'userDataSync.log'); this.keybindingsResource = joinPath(this.userRoamingDataHome, 'keybindings.json'); this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); - this.localeResource = joinPath(this.userRoamingDataHome, 'locale.json'); this.argvResource = joinPath(this.userRoamingDataHome, 'argv.json'); this.backupHome = joinPath(this.userRoamingDataHome, BACKUPS); this.configuration.backupWorkspaceResource = joinPath(this.backupHome, options.workspaceId); @@ -146,7 +145,6 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment settingsResource: URI; keybindingsResource: URI; keyboardLayoutResource: URI; - localeResource: URI; argvResource: URI; settingsSyncPreviewResource: URI; userDataSyncLogResource: URI; diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index b42e5d9fa73..c6c9a1f1917 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -783,11 +783,6 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return 'keybindings'; } - // Check for locale file - if (isEqual(this.resource, joinPath(this.environmentService.userRoamingDataHome, 'locale.json'))) { - return 'locale'; - } - // Check for snippets if (isEqualOrParent(this.resource, joinPath(this.environmentService.userRoamingDataHome, 'snippets'))) { return 'snippets'; From ffaaf4fe0d61013c6f6449e2bf1c1bb03aec2be1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 07:47:37 +0200 Subject: [PATCH 344/435] :lipstick: --- .../browser/parts/activitybar/activitybarPart.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index fc2f2bf42b8..e3773ffb286 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -5,7 +5,6 @@ import 'vs/css!./media/activitybarpart'; import * as nls from 'vs/nls'; -import { illegalArgument } from 'vs/base/common/errors'; import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -15,7 +14,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; @@ -75,7 +74,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private cachedViewlets: ICachedViewlet[] = []; private compositeBar: CompositeBar; - private compositeActions: Map = new Map(); + private readonly compositeActions: Map = new Map(); private readonly viewletDisposables: Map = new Map(); @@ -169,7 +168,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (foundViewlet) { this.compositeBar.addComposite(foundViewlet); } + this.compositeBar.activateComposite(viewlet.getId()); + const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId()); if (viewletDescriptor) { const viewContainer = this.getViewContainer(viewletDescriptor.id); @@ -191,7 +192,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { return this.showGlobalActivity(badge, clazz); } - throw illegalArgument('globalActivityId'); + return Disposable.None; } private showGlobalActivity(badge: IBadge, clazz?: string): IDisposable { @@ -222,7 +223,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Menubar: install a custom menu bar depending on configuration this.customMenubar = this._register(this.instantiationService.createInstance(CustomMenubarControl)); this.customMenubar.create(this.menubar); - } createContentArea(parent: HTMLElement): HTMLElement { @@ -295,6 +295,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { name: nls.localize('manage', "Manage"), cssClass: 'update-activity' }); + this.globalActivityActionBar.push(this.globalActivityAction); } @@ -340,6 +341,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } } } + for (const viewlet of viewlets) { this.enableCompositeActions(viewlet); const viewContainer = this.getViewContainer(viewlet.id); @@ -358,6 +360,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (disposable) { disposable.dispose(); } + this.viewletDisposables.delete(viewletId); this.hideComposite(viewletId); } @@ -375,6 +378,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { if (!viewContainer || !viewContainer.hideIfEmpty) { return false; } + return cachedViewlet && cachedViewlet.views && cachedViewlet.views.length ? cachedViewlet.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when))) : viewletId === TEST_VIEW_CONTAINER_ID /* Hide Test viewlet for the first time or it had no views registered before */; @@ -391,6 +395,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private hideComposite(compositeId: string): void { this.compositeBar.hideComposite(compositeId); + const compositeActions = this.compositeActions.get(compositeId); if (compositeActions) { compositeActions.activityAction.dispose(); From ab7d961f1d66d1d69a0d1f3c29026a1d9c03fd54 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 9 Oct 2019 23:28:18 -0700 Subject: [PATCH 345/435] Notifications icon polish (#82171) * Increase '!' icon in info/warning * Only show notification actions on hover * Increase notification icon size * Update icons for notification header actions * Always show actions in notifications * notifications - tweak visibility * fix enablement --- .../ui/codiconLabel/codicon/codicon.css | 2 +- .../ui/codiconLabel/codicon/codicon.ttf | Bin 52728 -> 52724 bytes .../notifications/media/notificationsList.css | 4 ++-- .../notifications/notificationsActions.ts | 4 ++-- .../notifications/notificationsCenter.ts | 11 +++++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index cd87edb95cf..3b7e393ed22 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?3b584136fb1f0186a1ee578cdcb5240b") format("truetype"); + src: url("./codicon.ttf?2fe2c4c835118d85ae7b4be128fe0c1f") format("truetype"); } .codicon[class*='codicon-'] { diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf index fff7ab51978252a9e4038024ab52f11a530a95e7..ad7cb8ed77a373322a12b362f1e01d1f2dc1663d 100644 GIT binary patch delta 206 zcmew{oB7LZ<_QiWn^;~MGB8M{Ffc6D$w*C15$n4bF)>7!Ilm`kVvDli1O^5su7dpH zlB??;Suijhm@{#Qfee@N63KXeo39Mq%r6*#;O618bufA}3!}dTzgR#_z?49)K%F3# zpn#xho0B9v+&GwxO_jw(l}#sqiq~e<^aFy)N(s8GKkaLO{n{Loz!_<5%*d{&&dI2# zYN{-1%V;dhc+;G5hV-Aa(u`aG&1O3J@35aA)3?8jdU{Oj|0dblgEdasnIZxJ5|u}m delta 210 zcmew|oB79V<_QiWt3od&GcZV|Ffc4N$Vg305eqqFF)>7!xxA-fVvDli6b1$+u7dpH zlB??;SuijhSTJ#ifsEug?wj%aHeVUInO`sf!Odm+^I-I57Dj&weu;p%fN6m|fqFq~ zK|w(?HYZ7TxN!(8iy8|8@#IhO+N^T+KrmS;L6>#+FUE5F%^?Y#k><*b;)>>~oJ_`| zKxLxJOakWr(xjPgfqG&HJ0gxb>HvJ<#IK6LzME0077t BLzn;n diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css index 4a000267835..8150f9673ea 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css @@ -38,6 +38,7 @@ height: 22px; margin-right: 4px; margin-left: 4px; + font-size: 18px; background-position: center; background-repeat: no-repeat; } @@ -70,8 +71,7 @@ } .monaco-workbench .notifications-list-container .notification-list-item:hover .notification-list-item-toolbar-container, -.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container, -.monaco-workbench .notifications-list-container .notification-list-item.expanded .notification-list-item-toolbar-container { +.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container { display: block; } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts index c2c688d9073..94bfac3f5cf 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts @@ -43,7 +43,7 @@ export class ClearAllNotificationsAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, 'codicon-close-all'); + super(id, label, 'codicon-clear-all'); } run(notification: INotificationViewItem): Promise { @@ -63,7 +63,7 @@ export class HideNotificationsCenterAction extends Action { label: string, @ICommandService private readonly commandService: ICommandService ) { - super(id, label, 'codicon-chevron-down'); + super(id, label, 'codicon-close'); } run(notification: INotificationViewItem): Promise { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index 2bab7f303cf..b3444fa21e7 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -38,6 +38,7 @@ export class NotificationsCenter extends Themable { private _isVisible: boolean | undefined; private workbenchDimensions: Dimension | undefined; private notificationsCenterVisibleContextKey: IContextKey; + private clearAllAction: ClearAllNotificationsAction | undefined; constructor( private container: HTMLElement, @@ -107,12 +108,14 @@ export class NotificationsCenter extends Themable { } private updateTitle(): void { - const notificationsCenterTitle = assertIsDefined(this.notificationsCenterTitle); + const [notificationsCenterTitle, clearAllAction] = assertAllDefined(this.notificationsCenterTitle, this.clearAllAction); if (this.model.notifications.length === 0) { notificationsCenterTitle.textContent = localize('notificationsEmpty', "No new notifications"); + clearAllAction.enabled = false; } else { notificationsCenterTitle.textContent = localize('notifications', "Notifications"); + clearAllAction.enabled = true; } } @@ -144,12 +147,12 @@ export class NotificationsCenter extends Themable { actionRunner })); + this.clearAllAction = this._register(this.instantiationService.createInstance(ClearAllNotificationsAction, ClearAllNotificationsAction.ID, ClearAllNotificationsAction.LABEL)); + notificationsToolBar.push(this.clearAllAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.clearAllAction) }); + const hideAllAction = this._register(this.instantiationService.createInstance(HideNotificationsCenterAction, HideNotificationsCenterAction.ID, HideNotificationsCenterAction.LABEL)); notificationsToolBar.push(hideAllAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(hideAllAction) }); - const clearAllAction = this._register(this.instantiationService.createInstance(ClearAllNotificationsAction, ClearAllNotificationsAction.ID, ClearAllNotificationsAction.LABEL)); - notificationsToolBar.push(clearAllAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(clearAllAction) }); - // Notifications List this.notificationsList = this.instantiationService.createInstance(NotificationsList, this.notificationsCenterContainer, { ariaLabel: localize('notificationsList', "Notifications List") From 8dc54740667caa787ecf25e309a9595ed6771c06 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 08:53:11 +0200 Subject: [PATCH 346/435] [themes] Debounce color theme selection. Fixes #71616 --- .../themes/browser/themes.contribution.ts | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 8dc089688b4..13570fa3888 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -14,7 +14,6 @@ import { IWorkbenchThemeService, COLOR_THEME_SETTING, ICON_THEME_SETTING, IColor import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/contrib/extensions/common/extensions'; 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 { IColorRegistry, Extensions as ColorRegistryExtensions } from 'vs/platform/theme/common/colorRegistry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Color } from 'vs/base/common/color'; @@ -52,34 +51,43 @@ export class SelectColorThemeAction extends Action { ...configurationEntries(this.extensionGalleryService, localize('installColorThemes', "Install Additional Color Themes...")) ]; - const selectTheme = (theme: ThemeItem, applyTheme: boolean) => { - let themeId = theme.id; - if (typeof theme.id === 'undefined') { // 'pick in marketplace' entry - if (applyTheme) { - openExtensionViewlet(this.viewletService, 'category:themes '); - } - themeId = currentTheme.id; - } - let target: ConfigurationTarget | undefined = undefined; - if (applyTheme) { - let confValue = this.configurationService.inspect(COLOR_THEME_SETTING); - target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; - } + let selectThemeTimeout: NodeJS.Timeout | undefined; - this.themeService.setColorTheme(themeId, target).then(undefined, - err => { - onUnexpectedError(err); - this.themeService.setColorTheme(currentTheme.id, undefined); + const selectTheme = (theme: ThemeItem, applyTheme: boolean) => { + if (selectThemeTimeout) { + clearTimeout(selectThemeTimeout); + } + selectThemeTimeout = setTimeout(() => { + selectThemeTimeout = undefined; + + let themeId = theme.id; + if (typeof theme.id === 'undefined') { // 'pick in marketplace' entry + if (applyTheme) { + openExtensionViewlet(this.viewletService, 'category:themes '); + } + themeId = currentTheme.id; } - ); + let target: ConfigurationTarget | undefined = undefined; + if (applyTheme) { + let confValue = this.configurationService.inspect(COLOR_THEME_SETTING); + target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; + } + + this.themeService.setColorTheme(themeId, target).then(undefined, + err => { + onUnexpectedError(err); + this.themeService.setColorTheme(currentTheme.id, undefined); + } + ); + }, applyTheme ? 0 : 200); }; const placeHolder = localize('themes.selectTheme', "Select Color Theme (Up/Down Keys to Preview)"); const autoFocusIndex = firstIndex(picks, p => isItem(p) && p.id === currentTheme.id); const activeItem: ThemeItem = picks[autoFocusIndex] as ThemeItem; - const delayer = new Delayer(100); - const chooseTheme = (theme: ThemeItem) => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0); - const tryTheme = (theme: ThemeItem) => delayer.trigger(() => selectTheme(theme, false)); + + const chooseTheme = (theme: ThemeItem) => selectTheme(theme || currentTheme, true); + const tryTheme = (theme: ThemeItem) => selectTheme(theme, false); return this.quickInputService.pick(picks, { placeHolder, activeItem, onDidFocus: tryTheme }) .then(chooseTheme); @@ -115,33 +123,40 @@ class SelectIconThemeAction extends Action { configurationEntries(this.extensionGalleryService, localize('installIconThemes', "Install Additional File Icon Themes...")) ); + let selectThemeTimeout: NodeJS.Timeout | undefined; + const selectTheme = (theme: ThemeItem, applyTheme: boolean) => { - let themeId = theme.id; - if (typeof theme.id === 'undefined') { // 'pick in marketplace' entry + if (selectThemeTimeout) { + clearTimeout(selectThemeTimeout); + } + selectThemeTimeout = setTimeout(() => { + selectThemeTimeout = undefined; + let themeId = theme.id; + if (typeof theme.id === 'undefined') { // 'pick in marketplace' entry + if (applyTheme) { + openExtensionViewlet(this.viewletService, 'tag:icon-theme '); + } + themeId = currentTheme.id; + } + let target: ConfigurationTarget | undefined = undefined; if (applyTheme) { - openExtensionViewlet(this.viewletService, 'tag:icon-theme '); + let confValue = this.configurationService.inspect(ICON_THEME_SETTING); + target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; } - themeId = currentTheme.id; - } - let target: ConfigurationTarget | undefined = undefined; - if (applyTheme) { - let confValue = this.configurationService.inspect(ICON_THEME_SETTING); - target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; - } - this.themeService.setFileIconTheme(themeId, target).then(undefined, - err => { - onUnexpectedError(err); - this.themeService.setFileIconTheme(currentTheme.id, undefined); - } - ); + this.themeService.setFileIconTheme(themeId, target).then(undefined, + err => { + onUnexpectedError(err); + this.themeService.setFileIconTheme(currentTheme.id, undefined); + } + ); + }, applyTheme ? 0 : 200); }; const placeHolder = localize('themes.selectIconTheme', "Select File Icon Theme"); const autoFocusIndex = firstIndex(picks, p => isItem(p) && p.id === currentTheme.id); const activeItem: ThemeItem = picks[autoFocusIndex] as ThemeItem; - const delayer = new Delayer(100); - const chooseTheme = (theme: ThemeItem) => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0); - const tryTheme = (theme: ThemeItem) => delayer.trigger(() => selectTheme(theme, false)); + const chooseTheme = (theme: ThemeItem) => selectTheme(theme || currentTheme, true); + const tryTheme = (theme: ThemeItem) => selectTheme(theme, false); return this.quickInputService.pick(picks, { placeHolder, activeItem, onDidFocus: tryTheme }) .then(chooseTheme); From e921f24fc8c04aa540e0da656c8dcf3f5ed9b536 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 09:11:46 +0200 Subject: [PATCH 347/435] use window.setTimeout --- .../contrib/themes/browser/themes.contribution.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 13570fa3888..e389c436f63 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -51,13 +51,13 @@ export class SelectColorThemeAction extends Action { ...configurationEntries(this.extensionGalleryService, localize('installColorThemes', "Install Additional Color Themes...")) ]; - let selectThemeTimeout: NodeJS.Timeout | undefined; + let selectThemeTimeout: number | undefined; const selectTheme = (theme: ThemeItem, applyTheme: boolean) => { if (selectThemeTimeout) { clearTimeout(selectThemeTimeout); } - selectThemeTimeout = setTimeout(() => { + selectThemeTimeout = window.setTimeout(() => { selectThemeTimeout = undefined; let themeId = theme.id; @@ -123,13 +123,13 @@ class SelectIconThemeAction extends Action { configurationEntries(this.extensionGalleryService, localize('installIconThemes', "Install Additional File Icon Themes...")) ); - let selectThemeTimeout: NodeJS.Timeout | undefined; + let selectThemeTimeout: number | undefined; const selectTheme = (theme: ThemeItem, applyTheme: boolean) => { if (selectThemeTimeout) { clearTimeout(selectThemeTimeout); } - selectThemeTimeout = setTimeout(() => { + selectThemeTimeout = window.setTimeout(() => { selectThemeTimeout = undefined; let themeId = theme.id; if (typeof theme.id === 'undefined') { // 'pick in marketplace' entry From 3da9bcbb78e3bb8b957f3ca34ea676855b314898 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 09:19:26 +0200 Subject: [PATCH 348/435] JSON Language Server 1.2.2 --- extensions/json-language-features/server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 3559b36e9aa..f3ddc4293bb 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -1,7 +1,7 @@ { "name": "vscode-json-languageserver", "description": "JSON language server", - "version": "1.2.1", + "version": "1.2.2", "author": "Microsoft Corporation", "license": "MIT", "engines": { From 42d95e583b2bbc99a2661837b96b7779a28b7ad6 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 09:26:22 +0200 Subject: [PATCH 349/435] json ls-server readme: typos --- extensions/json-language-features/server/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/json-language-features/server/README.md b/extensions/json-language-features/server/README.md index dbc72d14601..71356e3c441 100644 --- a/extensions/json-language-features/server/README.md +++ b/extensions/json-language-features/server/README.md @@ -44,7 +44,7 @@ The JSON language server has the following dependencies on the client's capabili The client can send the following initialization options to the server: -- `provideFormatter: boolean | undefined`. If defined, the value defines wheter the server provides the `documentRangeFormattingProvider` capability on initialization. If undefined, the setting `json.format.enable` is used to determined wheter formatting is provided. The formatter will then be registered through dynamic registration. If the client does not support dynamic registration, no formatter will be available. +- `provideFormatter: boolean | undefined`. If defined, the value defines whether the server provides the `documentRangeFormattingProvider` capability on initialization. If undefined, the setting `json.format.enable` is used to determine whether formatting is provided. The formatter will then be registered through dynamic registration. If the client does not support dynamic registration, no formatter will be available. - `handledSchemaProtocols`: The URI schemas handles by the server. See section `Schema configuration` below. ### Settings @@ -60,7 +60,7 @@ The server supports the following settings: - `format` - `enable`: Whether the server should register the formatting support. This option is only applicable if the client supports *dynamicRegistration* for *rangeFormatting* and `initializationOptions.provideFormatter` is not defined. - `schema`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content. - - `fileMatch`: an array or file names or paths (separated by `/`). `*` can be used as a wildcard. + - `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard. - `url`: The URL of the schema, optional when also a schema is provided. - `schema`: The schema content. @@ -99,9 +99,9 @@ To find the schema for a given JSON document, the server uses the following mech - The settings define a schema association based on the documents URL. Settings can either associate a schema URL to a file or path pattern, and they can directly provide a schema. - Additionally, schema associations can also be provided by a custom 'schemaAssociations' configuration call. -Schemas are identified by URLs. To load the content of a schema, the JSON language server either tries to load from that URI or path itself, or delegates to the client. +Schemas are identified by URLs. To load the content of a schema, the JSON language server either tries to load from that URI or path itself or delegates to the client. -The `initializationOptions.handledSchemaProtocols` initialization option defines which URLs are handled by the server. Requests for all other URIs are send to the client. +The `initializationOptions.handledSchemaProtocols` initialization option defines which URLs are handled by the server. Requests for all other URIs are sent to the client. `handledSchemaProtocols` is part of the initialization options and can't be changed while the server is running. @@ -121,7 +121,7 @@ If `handledSchemaProtocols` is not set, the JSON language server will load the f #### Schema content request -Requests for schemas with URLs not handled by the server are forwarded to the client through an LSP request. This request is a JSON language server specific, non-standardized, extension to the LSP. +Requests for schemas with URLs not handled by the server are forwarded to the client through an LSP request. This request is a JSON language server-specific, non-standardized, extension to the LSP. Request: - method: 'vscode/content' @@ -130,12 +130,12 @@ Request: #### Schema content change notification -When the client is aware that a schema content has changed, it will notify the server through a notification. This notification is a JSON language server specific, non-standardized, extension to the LSP. +When the client is aware that a schema content has changed, it will notify the server through a notification. This notification is a JSON language server-specific, non-standardized, extension to the LSP. The server will, as a response, clear the schema content from the cache and reload the schema content when required again. #### Schema associations notification -In addition to the settings, schemas associations can also be provided through a notification from the client to the server. This notification is a JSON language server specific, non-standardized, extension to the LSP. +In addition to the settings, schemas associations can also be provided through a notification from the client to the server. This notification is a JSON language server-specific, non-standardized, extension to the LSP. Notification: - method: 'json/schemaAssociations' From 18dcbcc22e2f5bb99fd5661bd1cb3972e3da1098 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 10 Oct 2019 09:20:05 +0200 Subject: [PATCH 350/435] add breadcrumbs.filteredTypes-setting, #69279 --- src/vs/editor/common/modes.ts | 113 ++++++++++----- .../contrib/documentSymbols/outlineTree.ts | 17 ++- .../browser/quickOpen/quickOutline.ts | 4 +- .../browser/parts/editor/breadcrumbs.ts | 130 ++++++++++++++++++ .../parts/editor/breadcrumbsControl.ts | 6 +- .../browser/parts/editor/breadcrumbsModel.ts | 30 +++- .../browser/parts/editor/breadcrumbsPicker.ts | 16 ++- .../browser/callHierarchyTree.ts | 4 +- .../quickopen/browser/gotoSymbolHandler.ts | 4 +- .../search/browser/openSymbolHandler.ts | 8 +- .../parts/editor/breadcrumbModel.test.ts | 4 +- 11 files changed, 278 insertions(+), 58 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 70feadc2677..f7b1ea578a4 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -19,6 +19,7 @@ import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureR import { TokenizationRegistryImpl } from 'vs/editor/common/modes/tokenizationRegistry'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IMarkerData } from 'vs/platform/markers/common/markers'; +import { keys } from 'vs/base/common/map'; /** * Open ended enum at runtime @@ -874,40 +875,88 @@ export const enum SymbolTag { /** * @internal */ -export const symbolKindToCssClass = (function () { +export namespace SymbolKinds { - const _fromMapping: { [n: number]: string } = Object.create(null); - _fromMapping[SymbolKind.File] = 'file'; - _fromMapping[SymbolKind.Module] = 'module'; - _fromMapping[SymbolKind.Namespace] = 'namespace'; - _fromMapping[SymbolKind.Package] = 'package'; - _fromMapping[SymbolKind.Class] = 'class'; - _fromMapping[SymbolKind.Method] = 'method'; - _fromMapping[SymbolKind.Property] = 'property'; - _fromMapping[SymbolKind.Field] = 'field'; - _fromMapping[SymbolKind.Constructor] = 'constructor'; - _fromMapping[SymbolKind.Enum] = 'enum'; - _fromMapping[SymbolKind.Interface] = 'interface'; - _fromMapping[SymbolKind.Function] = 'function'; - _fromMapping[SymbolKind.Variable] = 'variable'; - _fromMapping[SymbolKind.Constant] = 'constant'; - _fromMapping[SymbolKind.String] = 'string'; - _fromMapping[SymbolKind.Number] = 'number'; - _fromMapping[SymbolKind.Boolean] = 'boolean'; - _fromMapping[SymbolKind.Array] = 'array'; - _fromMapping[SymbolKind.Object] = 'object'; - _fromMapping[SymbolKind.Key] = 'key'; - _fromMapping[SymbolKind.Null] = 'null'; - _fromMapping[SymbolKind.EnumMember] = 'enum-member'; - _fromMapping[SymbolKind.Struct] = 'struct'; - _fromMapping[SymbolKind.Event] = 'event'; - _fromMapping[SymbolKind.Operator] = 'operator'; - _fromMapping[SymbolKind.TypeParameter] = 'type-parameter'; + const byName = new Map(); + byName.set('file', SymbolKind.File); + byName.set('module', SymbolKind.Module); + byName.set('namespace', SymbolKind.Namespace); + byName.set('package', SymbolKind.Package); + byName.set('class', SymbolKind.Class); + byName.set('method', SymbolKind.Method); + byName.set('property', SymbolKind.Property); + byName.set('field', SymbolKind.Field); + byName.set('constructor', SymbolKind.Constructor); + byName.set('enum', SymbolKind.Enum); + byName.set('interface', SymbolKind.Interface); + byName.set('function', SymbolKind.Function); + byName.set('variable', SymbolKind.Variable); + byName.set('constant', SymbolKind.Constant); + byName.set('string', SymbolKind.String); + byName.set('number', SymbolKind.Number); + byName.set('boolean', SymbolKind.Boolean); + byName.set('array', SymbolKind.Array); + byName.set('object', SymbolKind.Object); + byName.set('key', SymbolKind.Key); + byName.set('null', SymbolKind.Null); + byName.set('enum-member', SymbolKind.EnumMember); + byName.set('struct', SymbolKind.Struct); + byName.set('event', SymbolKind.Event); + byName.set('operator', SymbolKind.Operator); + byName.set('type-parameter', SymbolKind.TypeParameter); - return function toCssClassName(kind: SymbolKind, inline?: boolean): string { - return `symbol-icon ${inline ? 'inline' : 'block'} ${_fromMapping[kind] || 'property'}`; - }; -})(); + const byKind = new Map(); + byKind.set(SymbolKind.File, 'file'); + byKind.set(SymbolKind.Module, 'module'); + byKind.set(SymbolKind.Namespace, 'namespace'); + byKind.set(SymbolKind.Package, 'package'); + byKind.set(SymbolKind.Class, 'class'); + byKind.set(SymbolKind.Method, 'method'); + byKind.set(SymbolKind.Property, 'property'); + byKind.set(SymbolKind.Field, 'field'); + byKind.set(SymbolKind.Constructor, 'constructor'); + byKind.set(SymbolKind.Enum, 'enum'); + byKind.set(SymbolKind.Interface, 'interface'); + byKind.set(SymbolKind.Function, 'function'); + byKind.set(SymbolKind.Variable, 'variable'); + byKind.set(SymbolKind.Constant, 'constant'); + byKind.set(SymbolKind.String, 'string'); + byKind.set(SymbolKind.Number, 'number'); + byKind.set(SymbolKind.Boolean, 'boolean'); + byKind.set(SymbolKind.Array, 'array'); + byKind.set(SymbolKind.Object, 'object'); + byKind.set(SymbolKind.Key, 'key'); + byKind.set(SymbolKind.Null, 'null'); + byKind.set(SymbolKind.EnumMember, 'enum-member'); + byKind.set(SymbolKind.Struct, 'struct'); + byKind.set(SymbolKind.Event, 'event'); + byKind.set(SymbolKind.Operator, 'operator'); + byKind.set(SymbolKind.TypeParameter, 'type-parameter'); + /** + * @internal + */ + export function fromString(value: string): SymbolKind | undefined { + return byName.get(value); + } + /** + * @internal + */ + export function names(): readonly string[] { + return keys(byName); + } + /** + * @internal + */ + export function toString(kind: SymbolKind): string | undefined { + return byKind.get(kind); + } + /** + * @internal + */ + export function toCssClassName(kind: SymbolKind, inline?: boolean): string { + return `symbol-icon ${inline ? 'inline' : 'block'} ${byKind.get(kind) || 'property'}`; + } +} export interface DocumentSymbol { name: string; diff --git a/src/vs/editor/contrib/documentSymbols/outlineTree.ts b/src/vs/editor/contrib/documentSymbols/outlineTree.ts index 4b96ccf9240..10fc800bf85 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineTree.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineTree.ts @@ -6,13 +6,13 @@ import * as dom from 'vs/base/browser/dom'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; -import { IDataSource, ITreeNode, ITreeRenderer, ITreeSorter } from 'vs/base/browser/ui/tree/tree'; +import { IDataSource, ITreeNode, ITreeRenderer, ITreeSorter, ITreeFilter } from 'vs/base/browser/ui/tree/tree'; import { values } from 'vs/base/common/collections'; import { createMatches, FuzzyScore } from 'vs/base/common/filters'; import 'vs/css!./media/outlineTree'; import 'vs/css!./media/symbol-icons'; import { Range } from 'vs/editor/common/core/range'; -import { SymbolKind, symbolKindToCssClass, SymbolTag } from 'vs/editor/common/modes'; +import { SymbolKind, SymbolKinds, SymbolTag } from 'vs/editor/common/modes'; import { OutlineElement, OutlineGroup, OutlineModel } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; @@ -125,7 +125,7 @@ export class OutlineElementRenderer implements ITreeRenderer= 0) { options.extraClasses.push(`deprecated`); @@ -214,6 +214,17 @@ export const enum OutlineSortOrder { ByKind } +export class OutlineFilter implements ITreeFilter { + + constructor( + public filteredTypes = new Set() + ) { } + + filter(element: OutlineItem): boolean { + return !(element instanceof OutlineElement) || !this.filteredTypes.has(element.symbol.kind); + } +} + export class OutlineItemComparator implements ITreeSorter { private readonly _collator = new IdleValue(() => new Intl.Collator(undefined, { numeric: true })); diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index eeeaf6f32c8..8bd72a304a2 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -15,7 +15,7 @@ import { ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editor import { IRange, Range } from 'vs/editor/common/core/range'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { DocumentSymbol, DocumentSymbolProviderRegistry, symbolKindToCssClass } from 'vs/editor/common/modes'; +import { DocumentSymbol, DocumentSymbolProviderRegistry, SymbolKinds } from 'vs/editor/common/modes'; import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen'; import { BaseEditorQuickOpenAction, IDecorator } from 'vs/editor/standalone/browser/quickOpen/editorQuickOpen'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -198,7 +198,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { } // Add - results.push(this.symbolEntry(label, symbolKindToCssClass(element.kind), description, element.range, highlights, editor, controller)); + results.push(this.symbolEntry(label, SymbolKinds.toCssClassName(element.kind), description, element.range, highlights, editor, controller)); } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts index df27f82a684..fdb54c058b5 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts @@ -166,6 +166,136 @@ Registry.as(Extensions.Configuration).registerConfigurat description: localize('icons', "Render breadcrumb items with icons."), type: 'boolean', default: true + }, + 'breadcrumbs.filteredTypes.file': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.file', "When set to `false` breadcrumbs never show `file`-symbols.") + }, + 'breadcrumbs.filteredTypes.module': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.module', "When set to `false` breadcrumbs never show `module`-symbols.") + }, + 'breadcrumbs.filteredTypes.namespace': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.namespace', "When set to `false` breadcrumbs never show `namespace`-symbols.") + }, + 'breadcrumbs.filteredTypes.package': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.package', "When set to `false` breadcrumbs never show `package`-symbols.") + }, + 'breadcrumbs.filteredTypes.class': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.class', "When set to `false` breadcrumbs never show `class`-symbols.") + }, + 'breadcrumbs.filteredTypes.method': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.method', "When set to `false` breadcrumbs never show `method`-symbols.") + }, + 'breadcrumbs.filteredTypes.property': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.property', "When set to `false` breadcrumbs never show `property`-symbols.") + }, + 'breadcrumbs.filteredTypes.field': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.field', "When set to `false` breadcrumbs never show `field`-symbols.") + }, + 'breadcrumbs.filteredTypes.constructor': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.constructor', "When set to `false` breadcrumbs never show `constructor`-symbols.") + }, + 'breadcrumbs.filteredTypes.enum': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.enum', "When set to `false` breadcrumbs never show `enum`-symbols.") + }, + 'breadcrumbs.filteredTypes.interface': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.interface', "When set to `false` breadcrumbs never show `interface`-symbols.") + }, + 'breadcrumbs.filteredTypes.function': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.function', "When set to `false` breadcrumbs never show `function`-symbols.") + }, + 'breadcrumbs.filteredTypes.variable': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.variable', "When set to `false` breadcrumbs never show `variable`-symbols.") + }, + 'breadcrumbs.filteredTypes.constant': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.constant', "When set to `false` breadcrumbs never show `constant`-symbols.") + }, + 'breadcrumbs.filteredTypes.string': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.string', "When set to `false` breadcrumbs never show `string`-symbols.") + }, + 'breadcrumbs.filteredTypes.number': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.number', "When set to `false` breadcrumbs never show `number`-symbols.") + }, + 'breadcrumbs.filteredTypes.boolean': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.boolean', "When set to `false` breadcrumbs never show `boolean`-symbols.") + }, + 'breadcrumbs.filteredTypes.array': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.array', "When set to `false` breadcrumbs never show `array`-symbols.") + }, + 'breadcrumbs.filteredTypes.object': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.object', "When set to `false` breadcrumbs never show `object`-symbols.") + }, + 'breadcrumbs.filteredTypes.key': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.key', "When set to `false` breadcrumbs never show `key`-symbols.") + }, + 'breadcrumbs.filteredTypes.null': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.null', "When set to `false` breadcrumbs never show `null`-symbols.") + }, + 'breadcrumbs.filteredTypes.enumMember': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.enumMember', "When set to `false` breadcrumbs never show `enumMember`-symbols.") + }, + 'breadcrumbs.filteredTypes.struct': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.struct', "When set to `false` breadcrumbs never show `struct`-symbols.") + }, + 'breadcrumbs.filteredTypes.event': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.event', "When set to `false` breadcrumbs never show `event`-symbols.") + }, + 'breadcrumbs.filteredTypes.operator': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.operator', "When set to `false` breadcrumbs never show `operator`-symbols.") + }, + 'breadcrumbs.filteredTypes.typeParameter': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.typeParameter', "When set to `false` breadcrumbs never show `typeParameter`-symbols.") } } }); diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 81ff34d2a50..d102ba46008 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -17,7 +17,7 @@ import 'vs/css!./media/breadcrumbscontrol'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; import { ICodeEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; -import { symbolKindToCssClass } from 'vs/editor/common/modes'; +import { SymbolKinds } from 'vs/editor/common/modes'; import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; @@ -109,7 +109,7 @@ class Item extends BreadcrumbsItem { // symbol if (this.options.showSymbolIcons) { let icon = document.createElement('div'); - icon.className = symbolKindToCssClass(this.element.symbol.kind); + icon.className = SymbolKinds.toCssClassName(this.element.symbol.kind); container.appendChild(icon); dom.addClass(container, 'shows-symbol-icon'); } @@ -246,7 +246,7 @@ export class BreadcrumbsControl { const uri = input.getResource()!; const editor = this._getActiveCodeEditor(); - const model = new EditorBreadcrumbsModel(uri, editor, this._workspaceService, this._configurationService); + const model = new EditorBreadcrumbsModel(uri, editor, this._configurationService, this._workspaceService); dom.toggleClass(this.domNode, 'relative-path', model.isRelative()); dom.toggleClass(this.domNode, 'backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\'); diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts index c6f7164cc8e..44a223f32fc 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts @@ -14,7 +14,7 @@ import { isEqual, dirname } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IPosition } from 'vs/editor/common/core/position'; -import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; +import { DocumentSymbolProviderRegistry, SymbolKinds } from 'vs/editor/common/modes'; import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Schemas } from 'vs/base/common/network'; @@ -51,16 +51,15 @@ export class EditorBreadcrumbsModel { constructor( private readonly _uri: URI, private readonly _editor: ICodeEditor | undefined, + @IConfigurationService private readonly _configurationService: IConfigurationService, @IWorkspaceContextService workspaceService: IWorkspaceContextService, - @IConfigurationService configurationService: IConfigurationService, ) { - this._cfgFilePath = BreadcrumbsConfig.FilePath.bindTo(configurationService); - this._cfgSymbolPath = BreadcrumbsConfig.SymbolPath.bindTo(configurationService); + this._cfgFilePath = BreadcrumbsConfig.FilePath.bindTo(_configurationService); + this._cfgSymbolPath = BreadcrumbsConfig.SymbolPath.bindTo(_configurationService); this._disposables.add(this._cfgFilePath.onDidChange(_ => this._onDidUpdate.fire(this))); this._disposables.add(this._cfgSymbolPath.onDidChange(_ => this._onDidUpdate.fire(this))); - this._fileInfo = EditorBreadcrumbsModel._initFilePathInfo(this._uri, workspaceService); this._bindToEditor(); this._onDidUpdate.fire(this); @@ -138,6 +137,14 @@ export class EditorBreadcrumbsModel { this._disposables.add(this._editor.onDidChangeModel(_ => this._updateOutline())); this._disposables.add(this._editor.onDidChangeModelLanguage(_ => this._updateOutline())); + // update when config changes (re-render) + this._disposables.add(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('breadcrumbs.filteredTypes')) { + this._updateOutline(true); + } + })); + + // update soon'ish as model content change const updateSoon = new TimeoutTimer(); this._disposables.add(updateSoon); @@ -221,7 +228,18 @@ export class EditorBreadcrumbsModel { } item = parent; } - return chain.reverse(); + let result: Array = []; + for (let i = chain.length - 1; i >= 0; i--) { + let element = chain[i]; + if ( + element instanceof OutlineElement + && !this._configurationService.getValue(`breadcrumbs.filteredTypes.${SymbolKinds.toString(element.symbol.kind)}`) + ) { + break; + } + result.push(element); + } + return result; } private _updateOutlineElements(elements: Array): void { diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts index b34cd439d03..2480f51eb92 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts @@ -26,8 +26,9 @@ import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs import { BreadcrumbElement, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter } from 'vs/base/browser/ui/tree/tree'; -import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list'; +import { SymbolKind, SymbolKinds } from 'vs/editor/common/modes'; export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker { const ctor: IConstructorSignature1 = element instanceof FileElement @@ -450,7 +451,8 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { multipleSelectionSupport: false, sorter: new OutlineItemComparator(this._getOutlineItemCompareType()), identityProvider: new OutlineIdentityProvider(), - keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider() + keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(), + filter: new OutlineFilter(this._getOutlineFilteredTypes()) } ); } @@ -496,6 +498,16 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { return OutlineSortOrder.ByPosition; } } + + private _getOutlineFilteredTypes(): Set { + const result = new Set(); + for (const name of SymbolKinds.names()) { + if (!this._configurationService.getValue(`breadcrumbs.filteredTypes.${name}`)) { + result.add(SymbolKinds.fromString(name) || -1); + } + } + return result; + } } //#endregion diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts index b35134d13ff..37ab8463eb6 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts @@ -9,7 +9,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { FuzzyScore, createMatches } from 'vs/base/common/filters'; import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; -import { symbolKindToCssClass, Location } from 'vs/editor/common/modes'; +import { SymbolKinds, Location } from 'vs/editor/common/modes'; import { hash } from 'vs/base/common/hash'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { Range } from 'vs/editor/common/core/range'; @@ -140,7 +140,7 @@ export class CallRenderer implements ITreeRenderer Date: Thu, 10 Oct 2019 09:53:02 +0200 Subject: [PATCH 351/435] add outline.filteredTypes setting, #53034 --- .../contrib/documentSymbols/outlineTree.ts | 20 ++- .../browser/parts/editor/breadcrumbsPicker.ts | 13 +- .../outline/browser/outline.contribution.ts | 130 ++++++++++++++++++ .../contrib/outline/browser/outlinePanel.ts | 9 +- 4 files changed, 156 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/contrib/documentSymbols/outlineTree.ts b/src/vs/editor/contrib/documentSymbols/outlineTree.ts index 10fc800bf85..eb5fd2760fb 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineTree.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineTree.ts @@ -216,12 +216,26 @@ export const enum OutlineSortOrder { export class OutlineFilter implements ITreeFilter { + private readonly _filteredTypes = new Set(); + constructor( - public filteredTypes = new Set() - ) { } + private readonly _prefix: string, + @IConfigurationService private readonly _configService: IConfigurationService, + ) { + + } + + update() { + this._filteredTypes.clear(); + for (const name of SymbolKinds.names()) { + if (!this._configService.getValue(`${this._prefix}.${name}`)) { + this._filteredTypes.add(SymbolKinds.fromString(name) || -1); + } + } + } filter(element: OutlineItem): boolean { - return !(element instanceof OutlineElement) || !this.filteredTypes.has(element.symbol.kind); + return !(element instanceof OutlineElement) || !this._filteredTypes.has(element.symbol.kind); } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts index 2480f51eb92..233bcba1b35 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts @@ -28,7 +28,6 @@ import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/th import { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter } from 'vs/base/browser/ui/tree/tree'; import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list'; -import { SymbolKind, SymbolKinds } from 'vs/editor/common/modes'; export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker { const ctor: IConstructorSignature1 = element instanceof FileElement @@ -452,7 +451,7 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { sorter: new OutlineItemComparator(this._getOutlineItemCompareType()), identityProvider: new OutlineIdentityProvider(), keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(), - filter: new OutlineFilter(this._getOutlineFilteredTypes()) + filter: this._instantiationService.createInstance(OutlineFilter, 'breadcrumbs.filteredTypes') } ); } @@ -498,16 +497,6 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { return OutlineSortOrder.ByPosition; } } - - private _getOutlineFilteredTypes(): Set { - const result = new Set(); - for (const name of SymbolKinds.names()) { - if (!this._configurationService.getValue(`breadcrumbs.filteredTypes.${name}`)) { - result.add(SymbolKinds.fromString(name) || -1); - } - } - return result; - } } //#endregion diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 57cda74ad2d..d9fba5aba15 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -50,6 +50,136 @@ Registry.as(ConfigurationExtensions.Configuration).regis 'description': localize('outline.problems.badges', "Use badges for Errors & Warnings."), 'type': 'boolean', 'default': true + }, + 'outline.filteredTypes.file': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.file', "When set to `false` outline never shows `file`-symbols.") + }, + 'outline.filteredTypes.module': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.module', "When set to `false` outline never shows `module`-symbols.") + }, + 'outline.filteredTypes.namespace': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.namespace', "When set to `false` outline never shows `namespace`-symbols.") + }, + 'outline.filteredTypes.package': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.package', "When set to `false` outline never shows `package`-symbols.") + }, + 'outline.filteredTypes.class': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.class', "When set to `false` outline never shows `class`-symbols.") + }, + 'outline.filteredTypes.method': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.method', "When set to `false` outline never shows `method`-symbols.") + }, + 'outline.filteredTypes.property': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.property', "When set to `false` outline never shows `property`-symbols.") + }, + 'outline.filteredTypes.field': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.field', "When set to `false` outline never shows `field`-symbols.") + }, + 'outline.filteredTypes.constructor': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.constructor', "When set to `false` outline never shows `constructor`-symbols.") + }, + 'outline.filteredTypes.enum': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.enum', "When set to `false` outline never shows `enum`-symbols.") + }, + 'outline.filteredTypes.interface': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.interface', "When set to `false` outline never shows `interface`-symbols.") + }, + 'outline.filteredTypes.function': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.function', "When set to `false` outline never shows `function`-symbols.") + }, + 'outline.filteredTypes.variable': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.variable', "When set to `false` outline never shows `variable`-symbols.") + }, + 'outline.filteredTypes.constant': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.constant', "When set to `false` outline never shows `constant`-symbols.") + }, + 'outline.filteredTypes.string': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.string', "When set to `false` outline never shows `string`-symbols.") + }, + 'outline.filteredTypes.number': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.number', "When set to `false` outline never shows `number`-symbols.") + }, + 'outline.filteredTypes.boolean': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.boolean', "When set to `false` outline never shows `boolean`-symbols.") + }, + 'outline.filteredTypes.array': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.array', "When set to `false` outline never shows `array`-symbols.") + }, + 'outline.filteredTypes.object': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.object', "When set to `false` outline never shows `object`-symbols.") + }, + 'outline.filteredTypes.key': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.key', "When set to `false` outline never shows `key`-symbols.") + }, + 'outline.filteredTypes.null': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.null', "When set to `false` outline never shows `null`-symbols.") + }, + 'outline.filteredTypes.enumMember': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.enumMember', "When set to `false` outline never shows `enumMember`-symbols.") + }, + 'outline.filteredTypes.struct': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.struct', "When set to `false` outline never shows `struct`-symbols.") + }, + 'outline.filteredTypes.event': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.event', "When set to `false` outline never shows `event`-symbols.") + }, + 'outline.filteredTypes.operator': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.operator', "When set to `false` outline never shows `operator`-symbols.") + }, + 'outline.filteredTypes.typeParameter': { + type: 'boolean', + default: true, + markdownDescription: localize('filteredTypes.typeParameter', "When set to `false` outline never shows `typeParameter`-symbols.") } } }); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index 5ce17f17da2..720682801c1 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -40,7 +40,7 @@ import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { OutlineConfigKeys, OutlineViewFocused, OutlineViewFiltered } from 'vs/editor/contrib/documentSymbols/outline'; import { FuzzyScore } from 'vs/base/common/filters'; -import { OutlineDataSource, OutlineItemComparator, OutlineSortOrder, OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItem, OutlineIdentityProvider, OutlineNavigationLabelProvider } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { OutlineDataSource, OutlineItemComparator, OutlineSortOrder, OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItem, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IDataTreeViewState } from 'vs/base/browser/ui/tree/dataTree'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { basename } from 'vs/base/common/resources'; @@ -247,6 +247,7 @@ export class OutlinePanel extends ViewletPanel { private _treeDataSource!: OutlineDataSource; private _treeRenderer!: OutlineElementRenderer; private _treeComparator!: OutlineItemComparator; + private _treeFilter!: OutlineFilter; private _treeStates = new LRUCache(10); private readonly _contextKeyFocused: IContextKey; @@ -313,6 +314,7 @@ export class OutlinePanel extends ViewletPanel { this._treeRenderer = this._instantiationService.createInstance(OutlineElementRenderer); this._treeDataSource = new OutlineDataSource(); this._treeComparator = new OutlineItemComparator(this._outlineViewState.sortBy); + this._treeFilter = this._instantiationService.createInstance(OutlineFilter, 'outline.filteredTypes'); this._tree = this._instantiationService.createInstance( WorkbenchDataTree, 'OutlinePanel', @@ -326,6 +328,7 @@ export class OutlinePanel extends ViewletPanel { multipleSelectionSupport: false, filterOnType: this._outlineViewState.filterOnType, sorter: this._treeComparator, + filter: this._treeFilter, identityProvider: new OutlineIdentityProvider(), keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider() } @@ -364,6 +367,10 @@ export class OutlinePanel extends ViewletPanel { if (e.affectsConfiguration(OutlineConfigKeys.icons)) { this._tree.updateChildren(); } + if (e.affectsConfiguration('outline.filteredTypes')) { + this._treeFilter.update(); + this._tree.refilter(); + } })); this._register(this.onDidChangeBodyVisibility(visible => { From c0aee712695e0071f56ed881cfb292c26426f62f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 10:25:04 +0200 Subject: [PATCH 352/435] native tabs require macOS 10.13 at least --- src/vs/workbench/electron-browser/desktop.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-browser/desktop.contribution.ts b/src/vs/workbench/electron-browser/desktop.contribution.ts index 542252803db..b1398d6415f 100644 --- a/src/vs/workbench/electron-browser/desktop.contribution.ts +++ b/src/vs/workbench/electron-browser/desktop.contribution.ts @@ -308,7 +308,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat 'default': false, 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."), - 'included': isMacintosh && parseFloat(os.release()) >= 16 // Minimum: macOS Sierra (10.12.x = darwin 16.x) + 'included': isMacintosh && parseFloat(os.release()) >= 17 // Minimum: macOS Sierra (10.13.x = darwin 17.x) }, 'window.nativeFullScreen': { 'type': 'boolean', From 7ab14b67e682d0b30d0fa2db0b38284fa0a77d24 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 10:40:50 +0200 Subject: [PATCH 353/435] fixes #82212 --- src/vs/code/electron-main/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 368d7b42f3a..f193d0053fc 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -592,7 +592,7 @@ export class CodeApplication extends Disposable { // Catch file URLs if (uri.authority === Schemas.file && !!uri.path) { const cli = assign(Object.create(null), environmentService.args); - const urisToOpen = [{ fileUri: uri }]; + const urisToOpen = [{ fileUri: URI.file(uri.fsPath) }]; windowsMainService.open({ context: OpenContext.API, cli, urisToOpen, gotoLineMode: true }); From 3b473663d99e2b951bac456a6cb5b2d3fb786c2c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 10:49:50 +0200 Subject: [PATCH 354/435] comment --- src/vs/code/electron-main/app.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index f193d0053fc..d12ed43d636 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -592,6 +592,8 @@ export class CodeApplication extends Disposable { // Catch file URLs if (uri.authority === Schemas.file && !!uri.path) { const cli = assign(Object.create(null), environmentService.args); + + // hey Ben, we need to convert this `code://file` URI into a `file://` URI const urisToOpen = [{ fileUri: URI.file(uri.fsPath) }]; windowsMainService.open({ context: OpenContext.API, cli, urisToOpen, gotoLineMode: true }); From a8ec0bb74d601e7added42d66f2fac4b58ae8d29 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 11:00:02 +0200 Subject: [PATCH 355/435] Upgrading a theme currently requires a window reload. For #73306 --- .../themes/browser/workbenchThemeService.ts | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index e3368f14cc7..69483fa673e 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -177,6 +177,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // restore color this.setColorTheme(prevColorId, 'auto'); prevColorId = undefined; + } else { + this.reloadCurrentColorTheme(); } } } @@ -199,6 +201,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { if (this.currentIconTheme.id === DEFAULT_ICON_THEME_ID && !types.isUndefined(prevFileIconId) && await this.iconThemeStore.findThemeData(prevFileIconId)) { this.setFileIconTheme(prevFileIconId, 'auto'); prevFileIconId = undefined; + } else { + this.reloadCurrentFileIconTheme(); } } } @@ -206,18 +210,10 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.fileService.onFileChanges(async e => { if (this.watchedColorThemeLocation && this.currentColorTheme && e.contains(this.watchedColorThemeLocation, FileChangeType.UPDATED)) { - await this.currentColorTheme.reload(this.fileService); - this.currentColorTheme.setCustomColors(this.colorCustomizations); - this.currentColorTheme.setCustomTokenColors(this.tokenColorCustomizations); - this.updateDynamicCSSRules(this.currentColorTheme); - this.applyTheme(this.currentColorTheme, undefined, false); + this.reloadCurrentColorTheme(); } if (this.watchedIconThemeLocation && this.currentIconTheme && e.contains(this.watchedIconThemeLocation, FileChangeType.UPDATED)) { - await this.currentIconTheme.reload(this.fileService); - _applyIconTheme(this.currentIconTheme, () => { - this.doSetFileIconTheme(this.currentIconTheme); - return Promise.resolve(this.currentIconTheme); - }); + this.reloadCurrentFileIconTheme(); } }); } @@ -362,6 +358,14 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { }); } + private async reloadCurrentColorTheme() { + await this.currentColorTheme.reload(this.fileService); + this.currentColorTheme.setCustomColors(this.colorCustomizations); + this.currentColorTheme.setCustomTokenColors(this.tokenColorCustomizations); + this.updateDynamicCSSRules(this.currentColorTheme); + this.applyTheme(this.currentColorTheme, undefined, false); + } + public restoreColorTheme() { let colorThemeSetting = this.configurationService.getValue(COLOR_THEME_SETTING); if (colorThemeSetting !== this.currentColorTheme.settingsId) { @@ -499,6 +503,14 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { }); } + private async reloadCurrentFileIconTheme() { + await this.currentIconTheme.reload(this.fileService); + _applyIconTheme(this.currentIconTheme, () => { + this.doSetFileIconTheme(this.currentIconTheme); + return Promise.resolve(this.currentIconTheme); + }); + } + public restoreFileIconTheme() { let fileIconThemeSetting = this.configurationService.getValue(ICON_THEME_SETTING); if (fileIconThemeSetting !== this.currentIconTheme.settingsId) { From f60e33e1826bc683f39b3e531bcd8d19263f286f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 10 Oct 2019 11:25:31 +0200 Subject: [PATCH 356/435] tweak undo behaviour when inserting suggestion via commit character, fixes #44155 --- .../editor/contrib/suggest/suggestController.ts | 16 ++++++++-------- .../contrib/suggest/test/suggestModel.test.ts | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index f29143f81dc..f3aa1c65ad3 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -115,10 +115,10 @@ export class SuggestController implements IEditorContribution { const widget = this._instantiationService.createInstance(SuggestWidget, this._editor); this._toDispose.add(widget); - this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true), this)); + this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true), this)); // Wire up logic to accept a suggestion on certain characters - const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true)); + const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false)); this._toDispose.add(commitCharacterController); this._toDispose.add(this._model.onDidSuggest(e => { if (e.completionModel.items.length === 0) { @@ -223,7 +223,7 @@ export class SuggestController implements IEditorContribution { this._lineSuffix.dispose(); } - protected _insertSuggestion(event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStops: boolean): void { + protected _insertSuggestion(event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStopBefore: boolean, undoStopAfter: boolean): void { if (!event || !event.item) { this._alternatives.getValue().reset(); this._model.cancel(); @@ -242,7 +242,7 @@ export class SuggestController implements IEditorContribution { // pushing undo stops *before* additional text edits and // *after* the main edit - if (undoStops) { + if (undoStopBefore) { this._editor.pushUndoStop(); } @@ -270,7 +270,7 @@ export class SuggestController implements IEditorContribution { adjustWhitespace: !(suggestion.insertTextRules! & CompletionItemInsertTextRule.KeepWhitespace) }); - if (undoStops) { + if (undoStopAfter) { this._editor.pushUndoStop(); } @@ -300,7 +300,7 @@ export class SuggestController implements IEditorContribution { if (modelVersionNow !== model.getAlternativeVersionId()) { model.undo(); } - this._insertSuggestion(next, false, false); + this._insertSuggestion(next, false, false, false); break; } }); @@ -382,7 +382,7 @@ export class SuggestController implements IEditorContribution { return; } this._editor.pushUndoStop(); - this._insertSuggestion({ index, item, model: completionModel }, true, false); + this._insertSuggestion({ index, item, model: completionModel }, true, false, false); }, undefined, listener); }); @@ -394,7 +394,7 @@ export class SuggestController implements IEditorContribution { acceptSelectedSuggestion(keepAlternativeSuggestions?: boolean): void { const item = this._widget.getValue().getFocusedItem(); - this._insertSuggestion(item, !!keepAlternativeSuggestions, true); + this._insertSuggestion(item, !!keepAlternativeSuggestions, true, true); } acceptNextSuggestion() { diff --git a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts index d8e629d7c03..e489938804e 100644 --- a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts +++ b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts @@ -676,7 +676,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () { return withOracle(async (sugget, editor) => { class TestCtrl extends SuggestController { _insertSuggestion(item: ISelectedSuggestion) { - super._insertSuggestion(item, false, true); + super._insertSuggestion(item, false, true, true); } } const ctrl = editor.registerAndInstantiateContribution(TestCtrl); From c484b257204d442c77bd01f4beca7f3597cff1a1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 11:29:45 +0200 Subject: [PATCH 357/435] notifications - allow to configure a filter to silence notifications --- .../standalone/browser/simpleServices.ts | 4 ++- .../common/abstractKeybindingService.test.ts | 3 +- .../notification/common/notification.ts | 21 +++++++++++++ .../test/common/testNotificationService.ts | 6 ++-- .../configurationEditingService.test.ts | 2 +- .../common/notificationService.ts | 30 ++++++++++++++----- .../api/extHostMessagerService.test.ts | 10 +++++-- 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 121167d45ef..799e6e61e15 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -37,7 +37,7 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; import { ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label'; -import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { IProgressRunner, IEditorProgressService } from 'vs/platform/progress/common/progress'; import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -233,6 +233,8 @@ export class SimpleNotificationService implements INotificationService { public status(message: string | Error, options?: IStatusMessageOptions): IDisposable { return Disposable.None; } + + public setFilter(filter: NotificationsFilter): void { } } export class StandaloneCommandService implements ICommandService { diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index 84a31d13438..73f80cb4f68 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -159,7 +159,8 @@ suite('AbstractKeybindingService', () => { statusMessageCallsDisposed!.push(message); } }; - } + }, + setFilter() { } }; let resolver = new KeybindingResolver(items, []); diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index b16fe281725..663ba2070bf 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -227,6 +227,20 @@ export interface IStatusMessageOptions { hideAfter?: number; } +export enum NotificationsFilter { + + /** + * No filter is enabled. + */ + OFF, + + /** + * All notifications are configured as silent. See + * `INotificationProperties.silent` for more info. + */ + SILENT +} + /** * A service to bring up notifications and non-modal prompts. * @@ -286,6 +300,13 @@ export interface INotificationService { * @returns a disposable to hide the status message */ status(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable; + + /** + * Allows to configure a filter for notifications. + * + * @param filter the filter to use + */ + setFilter(filter: NotificationsFilter): void; } export class NoOpNotification implements INotificationHandle { diff --git a/src/vs/platform/notification/test/common/testNotificationService.ts b/src/vs/platform/notification/test/common/testNotificationService.ts index b4c4d4000fd..671339e55e9 100644 --- a/src/vs/platform/notification/test/common/testNotificationService.ts +++ b/src/vs/platform/notification/test/common/testNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; export class TestNotificationService implements INotificationService { @@ -35,4 +35,6 @@ export class TestNotificationService implements INotificationService { status(message: string | Error, options?: IStatusMessageOptions): IDisposable { return Disposable.None; } -} \ No newline at end of file + + setFilter(filter: NotificationsFilter): void { } +} diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index 55ca172c9ae..b74897ff0ed 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -185,7 +185,7 @@ suite('ConfigurationEditingService', () => { test('do not notify error', () => { instantiationService.stub(ITextFileService, 'isDirty', true); const target = sinon.stub(); - instantiationService.stub(INotificationService, { prompt: target, _serviceBrand: undefined, notify: null!, error: null!, info: null!, warn: null!, status: null! }); + instantiationService.stub(INotificationService, { prompt: target, _serviceBrand: undefined, notify: null!, error: null!, info: null!, warn: null!, status: null!, setFilter: null! }); return testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true }) .then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'), (error: ConfigurationEditingError) => { diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index 552e4e9fc51..cd8d98e2677 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { INotificationsModel, NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; @@ -17,15 +17,18 @@ export class NotificationService extends Disposable implements INotificationServ _serviceBrand: undefined; private _model: INotificationsModel = this._register(new NotificationsModel()); + get model(): INotificationsModel { return this._model; } - get model(): INotificationsModel { - return this._model; - } + private filter = NotificationsFilter.OFF; constructor(@IStorageService private readonly storageService: IStorageService) { super(); } + setFilter(filter: NotificationsFilter): void { + this.filter = filter; + } + info(message: NotificationMessage | NotificationMessage[]): void { if (Array.isArray(message)) { message.forEach(m => this.info(m)); @@ -33,7 +36,7 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.model.addNotification({ severity: Severity.Info, message }); + this.addNotification(Severity.Info, message); } warn(message: NotificationMessage | NotificationMessage[]): void { @@ -43,7 +46,7 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.model.addNotification({ severity: Severity.Warning, message }); + this.addNotification(Severity.Warning, message); } error(message: NotificationMessage | NotificationMessage[]): void { @@ -53,7 +56,16 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.model.addNotification({ severity: Severity.Error, message }); + this.addNotification(Severity.Error, message); + } + + private addNotification(severity: Severity, message: NotificationMessage): void { + const notification: INotification = { severity, message }; + if (this.filter === NotificationsFilter.SILENT) { + notification.silent = true; + } + + this.model.addNotification(notification); } notify(notification: INotification): INotificationHandle { @@ -96,6 +108,10 @@ export class NotificationService extends Disposable implements INotificationServ notification.actions = actions; } + if (this.filter === NotificationsFilter.SILENT) { + notification.silent = true; + } + // Show notification handle = this.model.addNotification(notification); diff --git a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts index b3fe2988ec7..64105b9c089 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMessageService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; @@ -55,6 +55,9 @@ const emptyNotificationService = new class implements INotificationService { status(message: string | Error, options?: IStatusMessageOptions): IDisposable { return Disposable.None; } + setFilter(filter: NotificationsFilter): void { + throw new Error('not implemented.'); + } }; class EmptyNotificationService implements INotificationService { @@ -78,11 +81,14 @@ class EmptyNotificationService implements INotificationService { throw new Error('Method not implemented.'); } prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { - throw new Error('not implemented'); + throw new Error('Method not implemented'); } status(message: string, options?: IStatusMessageOptions): IDisposable { return Disposable.None; } + setFilter(filter: NotificationsFilter): void { + throw new Error('Method not implemented.'); + } } suite('ExtHostMessageService', function () { From 61079a9db584914861523e9c85369e3e08b7f1d6 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Oct 2019 11:36:27 +0200 Subject: [PATCH 358/435] Fix bad empty string on commandLine in task types --- src/vs/vscode.d.ts | 2 +- src/vs/workbench/api/common/extHostTypes.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0c986857ad6..dcf606c6a46 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5222,7 +5222,7 @@ declare module 'vscode' { /** * The shell command line. Is `undefined` if created with a command and arguments. */ - commandLine: string; + commandLine: string | undefined; /** * The shell command. Is `undefined` if created with a full command line. diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 1d3a41a2f1d..a71f8c6ea52 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1709,11 +1709,11 @@ export class ShellExecution implements vscode.ShellExecution { } } - get commandLine(): string { - return this._commandLine ? this._commandLine : ''; + get commandLine(): string | undefined { + return this._commandLine; } - set commandLine(value: string) { + set commandLine(value: string | undefined) { if (typeof value !== 'string') { throw illegalArgument('commandLine'); } From e5cb7e9d2ed187e70037ee7f4e74eaf8f2f64f18 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 11:39:17 +0200 Subject: [PATCH 359/435] fixes #81361 --- .../contrib/scm/browser/dirtydiffDecorator.ts | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 1eaf7d22cd0..b639e3fbd74 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -17,7 +17,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { URI } from 'vs/base/common/uri'; -import { ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMService, ISCMRepository, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { registerThemingParticipant, ITheme, ICssStyleCollector, themeColorFromId, IThemeService } from 'vs/platform/theme/common/themeService'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; @@ -37,7 +37,7 @@ import { IDiffEditorOptions, EditorOption } from 'vs/editor/common/config/editor import { Action, IAction, ActionRunner } from 'vs/base/common/actions'; import { IActionBarOptions, ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { basename } from 'vs/base/common/resources'; +import { basename, isEqualOrParent } from 'vs/base/common/resources'; import { MenuId, IMenuService, IMenu, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; import { createAndFillInActionBarActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IChange, IEditorModel, ScrollType, IEditorContribution, IDiffEditorModel } from 'vs/editor/common/editorCommon'; @@ -951,6 +951,23 @@ function compareChanges(a: IChange, b: IChange): number { return a.originalEndLineNumber - b.originalEndLineNumber; } +function createProviderComparer(uri: URI): (a: ISCMProvider, b: ISCMProvider) => number { + return (a, b) => { + const aIsParent = isEqualOrParent(uri, a.rootUri!); + const bIsParent = isEqualOrParent(uri, b.rootUri!); + + if (aIsParent && bIsParent) { + return a.rootUri!.fsPath.length - b.rootUri!.fsPath.length; + } else if (aIsParent) { + return -1; + } else if (bIsParent) { + return 1; + } else { + return 0; + } + }; +} + export class DirtyDiffModel extends Disposable { private _originalModel: ITextModel | null = null; @@ -1082,13 +1099,25 @@ export class DirtyDiffModel extends Disposable { }); } - private getOriginalResource(): Promise { + private async getOriginalResource(): Promise { if (!this._editorModel) { return Promise.resolve(null); } const uri = this._editorModel.uri; - return first(this.scmService.repositories.map(r => () => r.provider.getOriginalResource(uri))); + const providers = this.scmService.repositories.map(r => r.provider); + const rootedProviders = providers.filter(p => !!p.rootUri); + + rootedProviders.sort(createProviderComparer(uri)); + + const result = await first(rootedProviders.map(p => () => p.getOriginalResource(uri))); + + if (result) { + return result; + } + + const nonRootedProviders = providers.filter(p => !p.rootUri); + return first(nonRootedProviders.map(p => () => p.getOriginalResource(uri))); } findNextClosestChange(lineNumber: number, inclusive = true): number { From d32da8db592e6f032e2c09c464740047122bbbe3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Oct 2019 11:40:03 +0200 Subject: [PATCH 360/435] [folding] configure plain text to use offSide folding. Fixes #73444 --- src/vs/editor/common/modes/modesRegistry.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/modes/modesRegistry.ts b/src/vs/editor/common/modes/modesRegistry.ts index fbdda5d65a4..ddc03651456 100644 --- a/src/vs/editor/common/modes/modesRegistry.ts +++ b/src/vs/editor/common/modes/modesRegistry.ts @@ -60,5 +60,8 @@ LanguageConfigurationRegistry.register(PLAINTEXT_LANGUAGE_IDENTIFIER, { ['(', ')'], ['[', ']'], ['{', '}'], - ] + ], + folding: { + offSide: true + } }); From ad3267819b2e65e3b9d32effedf181c044cd310e Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 10 Oct 2019 11:44:45 +0200 Subject: [PATCH 361/435] zen mode: silentNotifications --- src/vs/workbench/browser/layout.ts | 15 ++++++++++++++- .../workbench/browser/workbench.contribution.ts | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 81593caec80..be57658a338 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -37,6 +37,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { coalesce } from 'vs/base/common/arrays'; import { assertIsDefined } from 'vs/base/common/types'; +import { INotificationService, NotificationsFilter } from 'vs/platform/notification/common/notification'; enum Settings { MENUBAR_VISIBLE = 'window.menuBarVisibility', @@ -135,6 +136,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private viewletService: IViewletService; private contextService: IWorkspaceContextService; private backupFileService: IBackupFileService; + private notificationService: INotificationService; protected readonly state = { fullscreen: false, @@ -182,7 +184,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi transitionedToCenteredEditorLayout: false, wasSideBarVisible: false, wasPanelVisible: false, - transitionDisposables: new DisposableStore() + transitionDisposables: new DisposableStore(), + setNotificationsFilter: false }, }; @@ -210,6 +213,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.panelService = accessor.get(IPanelService); this.viewletService = accessor.get(IViewletService); this.titleService = accessor.get(ITitleService); + this.notificationService = accessor.get(INotificationService); accessor.get(IStatusbarService); // not used, but called to ensure instantiated accessor.get(IActivityBarService); // not used, but called to ensure instantiated @@ -650,6 +654,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi hideActivityBar: boolean; hideStatusBar: boolean; hideLineNumbers: boolean; + silentNotifications: boolean; } = this.configurationService.getValue('zenMode'); toggleFullScreen = !this.state.fullscreen && config.fullScreen; @@ -679,6 +684,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.state.zenMode.transitionDisposables.add(this.editorGroupService.enforcePartOptions({ showTabs: false })); } + this.state.zenMode.setNotificationsFilter = config.silentNotifications; + if (config.silentNotifications) { + this.notificationService.setFilter(NotificationsFilter.SILENT); + } + if (config.centerLayout) { this.centerEditorLayout(true, true); } @@ -704,6 +714,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.doUpdateLayoutConfiguration(true); this.editorGroupService.activeGroup.focus(); + if (this.state.zenMode.setNotificationsFilter) { + this.notificationService.setFilter(NotificationsFilter.OFF); + } toggleFullScreen = this.state.zenMode.transitionedToFullScreen && this.state.fullscreen; } diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index acc3d4b0129..df67efd0a94 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -364,6 +364,11 @@ import { isMacintosh, isWindows, isLinux, isWeb, isNative } from 'vs/base/common 'type': 'boolean', 'default': false, 'description': nls.localize('zenMode.restore', "Controls whether a window should restore to zen mode if it was exited in zen mode.") + }, + 'zenMode.silentNotifications': { + 'type': 'boolean', + 'default': true, + 'description': nls.localize('zenMode.silentNotifications', "Controls whether notifications are shown while in zen mode. If true, all notifications are silent and they will only appear in the status bar.") } } }); From 76db3ee4b7a92a7ff02882bb98e6a5658e0036d8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Oct 2019 11:45:14 +0200 Subject: [PATCH 362/435] Use setImmediate for yielding from tokenization --- src/vs/editor/common/model/textModelTokens.ts | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index 7749d45b6ad..cd257146b9e 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -16,6 +16,7 @@ import { TextModel } from 'vs/editor/common/model/textModel'; import { Disposable } from 'vs/base/common/lifecycle'; import { StopWatch } from 'vs/base/common/stopwatch'; import { MultilineTokensBuilder, countEOL } from 'vs/editor/common/model/tokensStore'; +import * as platform from 'vs/base/common/platform'; const enum Constants { CHEAP_TOKENIZATION_LENGTH_LIMIT = 2048 @@ -196,14 +197,14 @@ export class TextModelTokenization extends Disposable { private readonly _textModel: TextModel; private readonly _tokenizationStateStore: TokenizationStateStore; - private _revalidateTokensTimeout: any; + private _isDisposed: boolean; private _tokenizationSupport: ITokenizationSupport | undefined; constructor(textModel: TextModel) { super(); + this._isDisposed = false; this._textModel = textModel; this._tokenizationStateStore = new TokenizationStateStore(); - this._revalidateTokensTimeout = -1; this._register(TokenizationRegistry.onDidChange((e) => { const languageIdentifier = this._textModel.getLanguageIdentifier(); @@ -245,19 +246,11 @@ export class TextModelTokenization extends Disposable { } public dispose(): void { - this._clearTimers(); + this._isDisposed = true; super.dispose(); } - private _clearTimers(): void { - if (this._revalidateTokensTimeout !== -1) { - clearTimeout(this._revalidateTokensTimeout); - this._revalidateTokensTimeout = -1; - } - } - private _resetTokenizationState(): void { - this._clearTimers(); const [tokenizationSupport, initialState] = initializeTokenization(this._textModel); this._tokenizationSupport = tokenizationSupport; this._tokenizationStateStore.flush(initialState); @@ -265,11 +258,14 @@ export class TextModelTokenization extends Disposable { } private _beginBackgroundTokenization(): void { - if (this._textModel.isAttachedToEditor() && this._hasLinesToTokenize() && this._revalidateTokensTimeout === -1) { - this._revalidateTokensTimeout = setTimeout(() => { - this._revalidateTokensTimeout = -1; + if (this._textModel.isAttachedToEditor() && this._hasLinesToTokenize()) { + platform.setImmediate(() => { + if (this._isDisposed) { + // disposed in the meantime + return; + } this._revalidateTokensNow(); - }, 0); + }); } } From dd9fe1584978ec04c2e3a8ec12d61ca456f73880 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 11:48:55 +0200 Subject: [PATCH 363/435] notifications - hide toasts when filter is on --- .../notifications/notificationsToasts.ts | 9 ++++++- src/vs/workbench/common/notifications.ts | 26 ++++++++++++++----- .../common/notificationService.ts | 23 +++------------- .../test/common/notifications.test.ts | 9 ++++++- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 6a35cf36db8..d8087235f5e 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -18,7 +18,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { NotificationsToastsVisibleContext } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; -import { Severity } from 'vs/platform/notification/common/notification'; +import { Severity, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IHostService } from 'vs/workbench/services/host/browser/host'; @@ -92,6 +92,13 @@ export class NotificationsToasts extends Themable { // Update toasts on notification changes this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e))); }); + + // Filter + this._register(this.model.onDidFilterChange(filter => { + if (filter === NotificationsFilter.SILENT) { + this.hide(); + } + })); } private async onCanShowNotifications(): Promise { diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index f0a492bad2c..614d1e561bd 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions } from 'vs/platform/notification/common/notification'; +import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -23,9 +23,12 @@ export interface INotificationsModel { readonly notifications: INotificationViewItem[]; readonly onDidNotificationChange: Event; + readonly onDidFilterChange: Event; addNotification(notification: INotification): INotificationHandle; + setFilter(filter: NotificationsFilter): void; + // // Notifications as Status // @@ -126,18 +129,29 @@ export class NotificationsModel extends Disposable implements INotificationsMode private static readonly NO_OP_NOTIFICATION = new NoOpNotification(); - private readonly _onDidNotificationChange: Emitter = this._register(new Emitter()); + private readonly _onDidNotificationChange = this._register(new Emitter()); readonly onDidNotificationChange: Event = this._onDidNotificationChange.event; - private readonly _onDidStatusMessageChange: Emitter = this._register(new Emitter()); + private readonly _onDidStatusMessageChange = this._register(new Emitter()); readonly onDidStatusMessageChange: Event = this._onDidStatusMessageChange.event; + private readonly _onDidFilterChange = this._register(new Emitter()); + readonly onDidFilterChange: Event = this._onDidFilterChange.event; + private readonly _notifications: INotificationViewItem[] = []; get notifications(): INotificationViewItem[] { return this._notifications; } private _statusMessage: IStatusMessageViewItem | undefined; get statusMessage(): IStatusMessageViewItem | undefined { return this._statusMessage; } + private filter = NotificationsFilter.OFF; + + setFilter(filter: NotificationsFilter): void { + this.filter = filter; + + this._onDidFilterChange.fire(filter); + } + addNotification(notification: INotification): INotificationHandle { const item = this.createViewItem(notification); if (!item) { @@ -174,7 +188,7 @@ export class NotificationsModel extends Disposable implements INotificationsMode } private createViewItem(notification: INotification): INotificationViewItem | undefined { - const item = NotificationViewItem.create(notification); + const item = NotificationViewItem.create(notification, this.filter); if (!item) { return undefined; } @@ -400,7 +414,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie private readonly _onDidLabelChange: Emitter = this._register(new Emitter()); readonly onDidLabelChange: Event = this._onDidLabelChange.event; - static create(notification: INotification): INotificationViewItem | undefined { + static create(notification: INotification, filter: NotificationsFilter = NotificationsFilter.OFF): INotificationViewItem | undefined { if (!notification || !notification.message || isPromiseCanceledError(notification.message)) { return undefined; // we need a message to show } @@ -424,7 +438,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie actions = { primary: notification.message.actions }; } - return new NotificationViewItem(severity, notification.sticky, notification.silent, message, notification.source, actions); + return new NotificationViewItem(severity, notification.sticky, notification.silent || filter === NotificationsFilter.SILENT, message, notification.source, actions); } private static parseNotificationMessage(input: NotificationMessage): INotificationMessage | undefined { diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index cd8d98e2677..c32c0b9499b 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -19,14 +19,12 @@ export class NotificationService extends Disposable implements INotificationServ private _model: INotificationsModel = this._register(new NotificationsModel()); get model(): INotificationsModel { return this._model; } - private filter = NotificationsFilter.OFF; - constructor(@IStorageService private readonly storageService: IStorageService) { super(); } setFilter(filter: NotificationsFilter): void { - this.filter = filter; + this._model.setFilter(filter); } info(message: NotificationMessage | NotificationMessage[]): void { @@ -36,7 +34,7 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.addNotification(Severity.Info, message); + this.model.addNotification({ severity: Severity.Info, message }); } warn(message: NotificationMessage | NotificationMessage[]): void { @@ -46,7 +44,7 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.addNotification(Severity.Warning, message); + this.model.addNotification({ severity: Severity.Warning, message }); } error(message: NotificationMessage | NotificationMessage[]): void { @@ -56,16 +54,7 @@ export class NotificationService extends Disposable implements INotificationServ return; } - this.addNotification(Severity.Error, message); - } - - private addNotification(severity: Severity, message: NotificationMessage): void { - const notification: INotification = { severity, message }; - if (this.filter === NotificationsFilter.SILENT) { - notification.silent = true; - } - - this.model.addNotification(notification); + this.model.addNotification({ severity: Severity.Error, message }); } notify(notification: INotification): INotificationHandle { @@ -108,10 +97,6 @@ export class NotificationService extends Disposable implements INotificationServ notification.actions = actions; } - if (this.filter === NotificationsFilter.SILENT) { - notification.silent = true; - } - // Show notification handle = this.model.addNotification(notification); diff --git a/src/vs/workbench/test/common/notifications.test.ts b/src/vs/workbench/test/common/notifications.test.ts index 4c81c67b61a..5a9dd5781b7 100644 --- a/src/vs/workbench/test/common/notifications.test.ts +++ b/src/vs/workbench/test/common/notifications.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { NotificationsModel, NotificationViewItem, INotificationChangeEvent, NotificationChangeType, NotificationViewItemLabelKind, IStatusMessageChangeEvent, StatusMessageChangeType } from 'vs/workbench/common/notifications'; import { Action } from 'vs/base/common/actions'; -import { INotification, Severity } from 'vs/platform/notification/common/notification'; +import { INotification, Severity, NotificationsFilter } from 'vs/platform/notification/common/notification'; import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; suite('Notifications', () => { @@ -127,6 +127,13 @@ suite('Notifications', () => { assert.equal(links[2].title, 'Click to execute command \'without.title\''); assert.equal(links[2].length, '[Link 3](command:without.title)'.length); assert.equal(links[2].offset, 'Unable to [Link 1](http://link1.com) open [Link 2](command:open.me "Open This") and '.length); + + // Filter + let item8 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, NotificationsFilter.SILENT)!; + assert.equal(item8.silent, true); + + let item9 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, NotificationsFilter.OFF)!; + assert.equal(item9.silent, false); }); test('Model', () => { From 9f0d6a6d17506d7d10c132a85b5c420a588b83c5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Oct 2019 11:50:59 +0200 Subject: [PATCH 364/435] Yield every 1 ms from tokenization (fixes #40681) --- src/vs/editor/common/model/textModelTokens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index cd257146b9e..da1fc0abfbb 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -270,7 +270,7 @@ export class TextModelTokenization extends Disposable { } private _revalidateTokensNow(toLineNumber: number = this._textModel.getLineCount()): void { - const MAX_ALLOWED_TIME = 20; + const MAX_ALLOWED_TIME = 1; const builder = new MultilineTokensBuilder(); const sw = StopWatch.create(false); From e6af73db940052d03a2a3d753e044f577678b041 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 10 Oct 2019 12:23:30 +0200 Subject: [PATCH 365/435] debugCommands: check if threadId is number before using it --- .../contrib/debug/browser/debugCommands.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 3f1ec22ef44..62f3dd6d0a2 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -60,8 +60,9 @@ export const DISCONNECT_LABEL = nls.localize('disconnect', "Disconnect"); export const STOP_LABEL = nls.localize('stop', "Stop"); export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); -function getThreadAndRun(accessor: ServicesAccessor, threadId: number | undefined, run: (thread: IThread) => Promise): void { +function getThreadAndRun(accessor: ServicesAccessor, threadIdArg: number | any, run: (thread: IThread) => Promise): void { const debugService = accessor.get(IDebugService); + const threadId = typeof threadIdArg === 'number' ? threadIdArg : undefined; let thread: IThread | undefined; if (threadId) { debugService.getModel().getSessions().forEach(s => { @@ -119,21 +120,21 @@ export function registerCommands(): void { CommandsRegistry.registerCommand({ id: REVERSE_CONTINUE_ID, - handler: (accessor: ServicesAccessor, threadId: number | undefined) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, thread => thread.reverseContinue()); } }); CommandsRegistry.registerCommand({ id: STEP_BACK_ID, - handler: (accessor: ServicesAccessor, threadId: number | undefined) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, thread => thread.stepBack()); } }); CommandsRegistry.registerCommand({ id: TERMINATE_THREAD_ID, - handler: (accessor: ServicesAccessor, threadId: number | undefined) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, thread => thread.terminate()); } }); @@ -213,7 +214,7 @@ export function registerCommands(): void { weight: KeybindingWeight.WorkbenchContrib, primary: KeyCode.F10, when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'), - handler: (accessor: ServicesAccessor, threadId: number) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, (thread: IThread) => thread.next()); } }); @@ -223,7 +224,7 @@ export function registerCommands(): void { weight: KeybindingWeight.WorkbenchContrib + 10, // Have a stronger weight to have priority over full screen when debugging primary: KeyCode.F11, when: CONTEXT_IN_DEBUG_MODE, - handler: (accessor: ServicesAccessor, threadId: number) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, (thread: IThread) => thread.stepIn()); } }); @@ -233,7 +234,7 @@ export function registerCommands(): void { weight: KeybindingWeight.WorkbenchContrib, primary: KeyMod.Shift | KeyCode.F11, when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'), - handler: (accessor: ServicesAccessor, threadId: number) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, (thread: IThread) => thread.stepOut()); } }); @@ -243,7 +244,7 @@ export function registerCommands(): void { weight: KeybindingWeight.WorkbenchContrib, primary: KeyCode.F6, when: CONTEXT_DEBUG_STATE.isEqualTo('running'), - handler: (accessor: ServicesAccessor, threadId: number) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, thread => thread.pause()); } }); @@ -292,7 +293,7 @@ export function registerCommands(): void { weight: KeybindingWeight.WorkbenchContrib, primary: KeyCode.F5, when: CONTEXT_IN_DEBUG_MODE, - handler: (accessor: ServicesAccessor, threadId: number | undefined) => { + handler: (accessor: ServicesAccessor, threadId: number | any) => { getThreadAndRun(accessor, threadId, thread => thread.continue()); } }); From 2703975994fed75078ae2648be3aa995211ffd19 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 12:53:53 +0200 Subject: [PATCH 366/435] Make it easier to tell which status item will be disabled in context menu (fix #76544) --- src/vs/workbench/browser/parts/statusbar/statusbarPart.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 418c8b2a56f..970279684f1 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -308,8 +308,8 @@ class ToggleStatusbarEntryVisibilityAction extends Action { class HideStatusbarEntryAction extends Action { - constructor(id: string, private model: StatusbarViewModel) { - super(id, nls.localize('hide', "Hide"), undefined, true); + constructor(id: string, name: string, private model: StatusbarViewModel) { + super(id, nls.localize('hide', "Hide '{0}'", name), undefined, true); } run(): Promise { @@ -560,7 +560,7 @@ export class StatusbarPart extends Part implements IStatusbarService { if (statusEntryUnderMouse) { actions.push(new Separator()); - actions.push(new HideStatusbarEntryAction(statusEntryUnderMouse.id, this.viewModel)); + actions.push(new HideStatusbarEntryAction(statusEntryUnderMouse.id, statusEntryUnderMouse.name, this.viewModel)); } return actions; From b6138b95268aea0768f77ae8e4eacbcc0621bf07 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Oct 2019 12:55:59 +0200 Subject: [PATCH 367/435] Fixes #80825: Use   only on Windows --- .../common/modes/textToHtmlTokenizer.ts | 6 ++--- .../editor/common/viewModel/viewModelImpl.ts | 3 ++- .../common/modes/textToHtmlTokenizer.test.ts | 22 +++++++++---------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/common/modes/textToHtmlTokenizer.ts b/src/vs/editor/common/modes/textToHtmlTokenizer.ts index af5a682bc37..e98f2b37f19 100644 --- a/src/vs/editor/common/modes/textToHtmlTokenizer.ts +++ b/src/vs/editor/common/modes/textToHtmlTokenizer.ts @@ -24,7 +24,7 @@ export function tokenizeToString(text: string, tokenizationSupport: IReducedToke return _tokenizeToString(text, tokenizationSupport || fallback); } -export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens, colorMap: string[], startOffset: number, endOffset: number, tabSize: number): string { +export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens, colorMap: string[], startOffset: number, endOffset: number, tabSize: number, useNbsp: boolean): string { let result = `

`; let charIndex = startOffset; let tabsCharDelta = 0; @@ -46,7 +46,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize; tabsCharDelta += insertSpacesCount - 1; while (insertSpacesCount > 0) { - partContent += ' '; + partContent += useNbsp ? ' ' : ' '; insertSpacesCount--; } break; @@ -78,7 +78,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens break; case CharCode.Space: - partContent += ' '; + partContent += useNbsp ? ' ' : ' '; break; default: diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 01e9f36723c..a99279b51d0 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -24,6 +24,7 @@ import { ICoordinatesConverter, IOverviewRulerDecorations, IViewModel, MinimapLi import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations'; import { ITheme } from 'vs/platform/theme/common/themeService'; import { RunOnceScheduler } from 'vs/base/common/async'; +import * as platform from 'vs/base/common/platform'; const USE_IDENTITY_LINES_COLLECTION = true; @@ -713,7 +714,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel if (lineContent === '') { result += '
'; } else { - result += tokenizeLineToHTML(lineContent, lineTokens.inflate(), colorMap, startOffset, endOffset, tabSize); + result += tokenizeLineToHTML(lineContent, lineTokens.inflate(), colorMap, startOffset, endOffset, tabSize, platform.isWindows); } } diff --git a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts index a8c5071cb9e..77f96fc20af 100644 --- a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts +++ b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts @@ -105,7 +105,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { const colorMap = [null!, '#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff']; assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4, true), [ '
', 'Ciao', @@ -118,7 +118,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 12, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 12, 4, true), [ '
', 'Ciao', @@ -131,7 +131,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 11, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 11, 4, true), [ '
', 'Ciao', @@ -143,7 +143,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 1, 11, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 1, 11, 4, true), [ '
', 'iao', @@ -155,7 +155,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 4, 11, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 4, 11, 4, true), [ '
', ' ', @@ -166,7 +166,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 5, 11, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 5, 11, 4, true), [ '
', 'hello', @@ -176,7 +176,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 5, 10, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 5, 10, 4, true), [ '
', 'hello', @@ -185,7 +185,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 6, 9, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 6, 9, 4, true), [ '
', 'ell', @@ -238,7 +238,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { const colorMap = [null!, '#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff']; assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 21, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 21, 4, true), [ '
', '  ', @@ -252,7 +252,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4, true), [ '
', '  ', @@ -266,7 +266,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => { ); assert.equal( - tokenizeLineToHTML(text, lineTokens, colorMap, 0, 3, 4), + tokenizeLineToHTML(text, lineTokens, colorMap, 0, 3, 4, true), [ '
', '  ', From 13dc6f18ac5988cfdac285dd76c0232b1378b2dc Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Oct 2019 13:14:45 +0200 Subject: [PATCH 368/435] Add setting to turn off problem matcher prompt Fixes #62728 --- .../tasks/browser/abstractTaskService.ts | 6 ++++ .../tasks/browser/task.contribution.ts | 36 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index ec2a34ea079..339485761d6 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -674,6 +674,12 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } private shouldAttachProblemMatcher(task: Task): boolean { + const settingValue = this.configurationService.getValue('task.problemMatchers.neverPrompt'); + if (settingValue === true) { + return false; + } else if (task.type && Types.isStringArray(settingValue) && (settingValue.indexOf(task.type) >= 0)) { + return false; + } if (!this.canCustomize(task)) { return false; } diff --git a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts index 23ecbb6684a..c71ef786480 100644 --- a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts +++ b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts @@ -35,6 +35,11 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor import { RunAutomaticTasks, ManageAutomaticTaskRunning } from 'vs/workbench/contrib/tasks/browser/runAutomaticTasks'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; +import schemaVersion1 from '../common/jsonSchema_v1'; +import schemaVersion2, { updateProblemMatchers } from '../common/jsonSchema_v2'; +import { AbstractTaskService, ConfigureTaskAction } from 'vs/workbench/contrib/tasks/browser/abstractTaskService'; +import { tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; let tasksCategory = nls.localize('tasksCategory', "Tasks"); @@ -288,10 +293,6 @@ let schema: IJSONSchema = { } }; -import schemaVersion1 from '../common/jsonSchema_v1'; -import schemaVersion2, { updateProblemMatchers } from '../common/jsonSchema_v2'; -import { AbstractTaskService, ConfigureTaskAction } from 'vs/workbench/contrib/tasks/browser/abstractTaskService'; -import { tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration'; schema.definitions = { ...schemaVersion1.definitions, ...schemaVersion2.definitions, @@ -305,3 +306,30 @@ ProblemMatcherRegistry.onMatcherChanged(() => { updateProblemMatchers(); jsonRegistry.notifySchemaChanged(tasksSchemaId); }); + +const configurationRegistry = Registry.as(Extensions.Configuration); +configurationRegistry.registerConfiguration({ + id: 'task', + order: 100, + title: nls.localize('tasksConfigurationTitle', "Tasks"), + type: 'object', + properties: { + 'task.problemMatchers.neverPrompt': { + markdownDescription: nls.localize('task.problemMatchers.neverPrompt', "Configures whether to show the problem matcher prompt when running a task. Set to `true` to never promp, or use an array of task types to turn off prompting only for specific task types."), + 'oneOf': [ + { + type: 'boolean', + markdownDescription: nls.localize('task.problemMatchers.neverPrompt.boolean', 'Sets problem matcher prompting behavior for all tasks.') + }, + { + type: 'array', + items: { + type: 'string', + markdownDescription: nls.localize('task.problemMatchers.neverPrompt.array', 'An array of task types to never prompt for problem matchers on.') + } + } + ], + default: false + } + } +}); From 3a626d89a0916c1a478c8fac8b076d6b7dd87ca4 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 10 Oct 2019 13:36:48 +0200 Subject: [PATCH 369/435] shift+tab/shift+enter overwrite suffix when accepting a completion, #10266 --- .../contrib/suggest/suggestController.ts | 59 ++++++++++++++----- .../contrib/suggest/test/suggestModel.test.ts | 2 +- .../keybinding/common/keybindingsRegistry.ts | 5 +- .../workbench/contrib/debug/browser/repl.ts | 4 +- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index f3aa1c65ad3..26b1e1f45b8 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -22,7 +22,7 @@ import * as nls from 'vs/nls'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { Context as SuggestContext, CompletionItem } from './suggest'; import { SuggestAlternatives } from './suggestAlternatives'; import { State, SuggestModel } from './suggestModel'; @@ -34,7 +34,7 @@ import { IdleValue } from 'vs/base/common/async'; import { isObject } from 'vs/base/common/types'; import { CommitCharacterController } from './suggestCommitCharacters'; import { IPosition } from 'vs/editor/common/core/position'; -import { TrackedRangeStickiness, ITextModel } from 'vs/editor/common/model'; +import { TrackedRangeStickiness, ITextModel, IWordAtPosition } from 'vs/editor/common/model'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import * as platform from 'vs/base/common/platform'; @@ -115,10 +115,10 @@ export class SuggestController implements IEditorContribution { const widget = this._instantiationService.createInstance(SuggestWidget, this._editor); this._toDispose.add(widget); - this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true), this)); + this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true, false), this)); // Wire up logic to accept a suggestion on certain characters - const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false)); + const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false, false)); this._toDispose.add(commitCharacterController); this._toDispose.add(this._model.onDidSuggest(e => { if (e.completionModel.items.length === 0) { @@ -223,7 +223,12 @@ export class SuggestController implements IEditorContribution { this._lineSuffix.dispose(); } - protected _insertSuggestion(event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStopBefore: boolean, undoStopAfter: boolean): void { + protected _insertSuggestion( + event: ISelectedSuggestion | undefined, + keepAlternativeSuggestions: boolean, + undoStopBefore: boolean, undoStopAfter: boolean, + overwriteSuffix: boolean + ): void { if (!event || !event.item) { this._alternatives.getValue().reset(); this._model.cancel(); @@ -237,8 +242,8 @@ export class SuggestController implements IEditorContribution { const model = this._editor.getModel(); const modelVersionNow = model.getAlternativeVersionId(); const { completion: suggestion, position } = event.item; - const editorColumn = this._editor.getPosition().column; - const columnDelta = editorColumn - position.column; + const editorPosition = this._editor.getPosition(); + const columnDelta = editorPosition.column - position.column; // pushing undo stops *before* additional text edits and // *after* the main edit @@ -251,7 +256,7 @@ export class SuggestController implements IEditorContribution { } // keep item in memory - this._memoryService.memorize(model, this._editor.getPosition(), event.item); + this._memoryService.memorize(model, editorPosition, event.item); let { insertText } = suggestion; if (!(suggestion.insertTextRules! & CompletionItemInsertTextRule.InsertAsSnippet)) { @@ -260,7 +265,12 @@ export class SuggestController implements IEditorContribution { const overwriteBefore = position.column - suggestion.range.startColumn; const overwriteAfter = suggestion.range.endColumn - position.column; - const suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0; + + let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(position) : 0; + let word: IWordAtPosition | null; + if (overwriteAfter === 0 && overwriteSuffix && (word = model.getWordAtPosition(position))) { + suffixDelta += word.endColumn - position.column; + } SnippetController2.get(this._editor).insert(insertText, { overwriteBefore: overwriteBefore + columnDelta, @@ -300,7 +310,7 @@ export class SuggestController implements IEditorContribution { if (modelVersionNow !== model.getAlternativeVersionId()) { model.undo(); } - this._insertSuggestion(next, false, false, false); + this._insertSuggestion(next, false, false, false, overwriteSuffix); break; } }); @@ -382,7 +392,7 @@ export class SuggestController implements IEditorContribution { return; } this._editor.pushUndoStop(); - this._insertSuggestion({ index, item, model: completionModel }, true, false, false); + this._insertSuggestion({ index, item, model: completionModel }, true, false, false, false); }, undefined, listener); }); @@ -392,9 +402,9 @@ export class SuggestController implements IEditorContribution { this._editor.focus(); } - acceptSelectedSuggestion(keepAlternativeSuggestions?: boolean): void { + acceptSelectedSuggestion(keepAlternativeSuggestions: boolean, overwriteSuffix: boolean): void { const item = this._widget.getValue().getFocusedItem(); - this._insertSuggestion(item, !!keepAlternativeSuggestions, true, true); + this._insertSuggestion(item, keepAlternativeSuggestions, true, true, overwriteSuffix); } acceptNextSuggestion() { @@ -489,18 +499,37 @@ const SuggestCommand = EditorCommand.bindToContribution(Sugge registerEditorCommand(new SuggestCommand({ id: 'acceptSelectedSuggestion', precondition: SuggestContext.Visible, - handler: x => x.acceptSelectedSuggestion(true), kbOpts: { weight: weight, kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Tab + }, + handler(x, args) { + let overwriteSuffix: boolean; + if (typeof args !== 'object') { + overwriteSuffix = false; + } else if (typeof args.overwriteSuffix !== 'boolean') { + overwriteSuffix = false; + } else { + overwriteSuffix = args.overwriteSuffix; + } + x.acceptSelectedSuggestion(true, overwriteSuffix); } })); +KeybindingsRegistry.registerKeybindingRule({ + id: 'acceptSelectedSuggestion', + when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus), + primary: KeyMod.Shift | KeyCode.Tab, + secondary: [KeyMod.Shift | KeyCode.Enter], + args: { overwriteSuffix: true }, + weight +}); + registerEditorCommand(new SuggestCommand({ id: 'acceptSelectedSuggestionOnEnter', precondition: SuggestContext.Visible, - handler: x => x.acceptSelectedSuggestion(false), + handler: x => x.acceptSelectedSuggestion(false, false), kbOpts: { weight: weight, kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), diff --git a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts index e489938804e..88448ea0db7 100644 --- a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts +++ b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts @@ -676,7 +676,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () { return withOracle(async (sugget, editor) => { class TestCtrl extends SuggestController { _insertSuggestion(item: ISelectedSuggestion) { - super._insertSuggestion(item, false, true, true); + super._insertSuggestion(item, false, true, true, false); } } const ctrl = editor.registerAndInstantiateContribution(TestCtrl); diff --git a/src/vs/platform/keybinding/common/keybindingsRegistry.ts b/src/vs/platform/keybinding/common/keybindingsRegistry.ts index 3c30daf3ab4..5c3de02794b 100644 --- a/src/vs/platform/keybinding/common/keybindingsRegistry.ts +++ b/src/vs/platform/keybinding/common/keybindingsRegistry.ts @@ -38,6 +38,7 @@ export interface IKeybindings { export interface IKeybindingRule extends IKeybindings { id: string; weight: number; + args?: any; when: ContextKeyExpr | null | undefined; } @@ -132,7 +133,7 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry { if (actualKb && actualKb.primary) { const kk = createKeybinding(actualKb.primary, OS); if (kk) { - this._registerDefaultKeybinding(kk, rule.id, undefined, rule.weight, 0, rule.when); + this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, 0, rule.when); } } @@ -141,7 +142,7 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry { const k = actualKb.secondary[i]; const kk = createKeybinding(k, OS); if (kk) { - this._registerDefaultKeybinding(kk, rule.id, undefined, rule.weight, -i - 1, rule.when); + this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, -i - 1, rule.when); } } } diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index c4774d5c30b..3f37db94e30 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -919,7 +919,7 @@ class AcceptReplInputAction extends EditorAction { } run(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - SuggestController.get(editor).acceptSelectedSuggestion(); + SuggestController.get(editor).acceptSelectedSuggestion(false, false); accessor.get(IPrivateReplService).acceptReplInput(); } } @@ -941,7 +941,7 @@ class FilterReplAction extends EditorAction { } run(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - SuggestController.get(editor).acceptSelectedSuggestion(); + SuggestController.get(editor).acceptSelectedSuggestion(false, false); accessor.get(IPrivateReplService).focusRepl(); } } From fcd4e09fd4f0ba0ea4a737fc12dba36720238e63 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 10 Oct 2019 14:26:04 +0200 Subject: [PATCH 370/435] make overwrite suffix the default, #10266 --- .../contrib/suggest/suggestController.ts | 42 ++++++++++--------- .../workbench/contrib/debug/browser/repl.ts | 4 +- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 26b1e1f45b8..f8ab47834a4 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -115,10 +115,10 @@ export class SuggestController implements IEditorContribution { const widget = this._instantiationService.createInstance(SuggestWidget, this._editor); this._toDispose.add(widget); - this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true, false), this)); + this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true, true), this)); // Wire up logic to accept a suggestion on certain characters - const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false, false)); + const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false, true)); this._toDispose.add(commitCharacterController); this._toDispose.add(this._model.onDidSuggest(e => { if (e.completionModel.items.length === 0) { @@ -227,7 +227,7 @@ export class SuggestController implements IEditorContribution { event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStopBefore: boolean, undoStopAfter: boolean, - overwriteSuffix: boolean + keepSuffix: boolean ): void { if (!event || !event.item) { this._alternatives.getValue().reset(); @@ -263,13 +263,17 @@ export class SuggestController implements IEditorContribution { insertText = SnippetParser.escape(insertText); } - const overwriteBefore = position.column - suggestion.range.startColumn; - const overwriteAfter = suggestion.range.endColumn - position.column; - + let overwriteBefore = position.column - suggestion.range.startColumn; + let overwriteAfter = suggestion.range.endColumn - position.column; let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(position) : 0; let word: IWordAtPosition | null; - if (overwriteAfter === 0 && overwriteSuffix && (word = model.getWordAtPosition(position))) { - suffixDelta += word.endColumn - position.column; + if (!keepSuffix) { + // don't overwrite anything right of the cursor + overwriteAfter = 0; + + } else if (overwriteAfter === 0 && (word = model.getWordAtPosition(position))) { + // compute fallback overwrite length + overwriteAfter = word.endColumn - position.column; } SnippetController2.get(this._editor).insert(insertText, { @@ -310,7 +314,7 @@ export class SuggestController implements IEditorContribution { if (modelVersionNow !== model.getAlternativeVersionId()) { model.undo(); } - this._insertSuggestion(next, false, false, false, overwriteSuffix); + this._insertSuggestion(next, false, false, false, keepSuffix); break; } }); @@ -402,9 +406,9 @@ export class SuggestController implements IEditorContribution { this._editor.focus(); } - acceptSelectedSuggestion(keepAlternativeSuggestions: boolean, overwriteSuffix: boolean): void { + acceptSelectedSuggestion(keepAlternativeSuggestions: boolean, keepSuffix: boolean): void { const item = this._widget.getValue().getFocusedItem(); - this._insertSuggestion(item, keepAlternativeSuggestions, true, true, overwriteSuffix); + this._insertSuggestion(item, keepAlternativeSuggestions, true, true, keepSuffix); } acceptNextSuggestion() { @@ -505,15 +509,15 @@ registerEditorCommand(new SuggestCommand({ primary: KeyCode.Tab }, handler(x, args) { - let overwriteSuffix: boolean; + let keepSuffix: boolean; if (typeof args !== 'object') { - overwriteSuffix = false; - } else if (typeof args.overwriteSuffix !== 'boolean') { - overwriteSuffix = false; + keepSuffix = true; + } else if (typeof args.keepSuffix !== 'boolean') { + keepSuffix = true; } else { - overwriteSuffix = args.overwriteSuffix; + keepSuffix = args.keepSuffix; } - x.acceptSelectedSuggestion(true, overwriteSuffix); + x.acceptSelectedSuggestion(true, keepSuffix); } })); @@ -522,14 +526,14 @@ KeybindingsRegistry.registerKeybindingRule({ when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus), primary: KeyMod.Shift | KeyCode.Tab, secondary: [KeyMod.Shift | KeyCode.Enter], - args: { overwriteSuffix: true }, + args: { keepSuffix: false }, weight }); registerEditorCommand(new SuggestCommand({ id: 'acceptSelectedSuggestionOnEnter', precondition: SuggestContext.Visible, - handler: x => x.acceptSelectedSuggestion(false, false), + handler: x => x.acceptSelectedSuggestion(false, true), kbOpts: { weight: weight, kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 3f37db94e30..76d330bdc5c 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -919,7 +919,7 @@ class AcceptReplInputAction extends EditorAction { } run(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - SuggestController.get(editor).acceptSelectedSuggestion(false, false); + SuggestController.get(editor).acceptSelectedSuggestion(false, true); accessor.get(IPrivateReplService).acceptReplInput(); } } @@ -941,7 +941,7 @@ class FilterReplAction extends EditorAction { } run(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - SuggestController.get(editor).acceptSelectedSuggestion(false, false); + SuggestController.get(editor).acceptSelectedSuggestion(false, true); accessor.get(IPrivateReplService).focusRepl(); } } From db3dd377f0eeb361ba7d6a5f9b19e0e833b081d3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 10 Oct 2019 15:43:34 +0200 Subject: [PATCH 371/435] debt - migrate suggest filtered types setting to many dot form --- src/vs/editor/common/config/editorOptions.ts | 265 +++++++++---------- 1 file changed, 129 insertions(+), 136 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 65134543ae7..5602b987afa 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -2351,142 +2351,135 @@ class EditorSuggest extends BaseEditorOption Date: Thu, 10 Oct 2019 16:45:32 +0200 Subject: [PATCH 372/435] Fixes #49305: Call preventDefault on mouseup event for middle button when selectionClipboard is turned off --- .../codeEditor/browser/selectionClipboard.ts | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts index 074e43dd377..82057e3a115 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts @@ -5,9 +5,8 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; -import * as process from 'vs/base/common/process'; import * as platform from 'vs/base/common/platform'; -import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditor, IEditorMouseEvent } from 'vs/editor/browser/editorBrowser'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions'; import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; @@ -32,33 +31,12 @@ export class SelectionClipboard extends Disposable implements IEditorContributio } })); - this._register(editor.onMouseDown((e: IEditorMouseEvent) => { + this._register(editor.onMouseUp((e: IEditorMouseEvent) => { if (!isEnabled) { - return; - } - if (!editor.hasModel()) { - return; - } - if (e.event.middleButton) { - e.event.preventDefault(); - editor.focus(); - - if (e.target.position) { - editor.setPosition(e.target.position); + if (e.event.middleButton) { + // try to stop the upcoming paste + e.event.preventDefault(); } - - if (e.target.type === MouseTargetType.SCROLLBAR) { - return; - } - - process.nextTick(() => { - // TODO@Alex: electron weirdness: calling clipboard.readText('selection') generates a paste event, so no need to execute paste ourselves - clipboardService.readText('selection'); - // keybindingService.executeCommand(Handler.Paste, { - // text: clipboard.readText('selection'), - // pasteOnNewLine: false - // }); - }); } })); From 7152672e3f475cc5a817042b81180a2a1dabb590 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 10 Oct 2019 16:47:16 +0200 Subject: [PATCH 373/435] debug commands: better fix for checking if threadId is a number --- src/vs/workbench/contrib/debug/browser/debugCommands.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 62f3dd6d0a2..25a45e50d2f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -60,11 +60,10 @@ export const DISCONNECT_LABEL = nls.localize('disconnect', "Disconnect"); export const STOP_LABEL = nls.localize('stop', "Stop"); export const CONTINUE_LABEL = nls.localize('continueDebug', "Continue"); -function getThreadAndRun(accessor: ServicesAccessor, threadIdArg: number | any, run: (thread: IThread) => Promise): void { +function getThreadAndRun(accessor: ServicesAccessor, threadId: number | any, run: (thread: IThread) => Promise): void { const debugService = accessor.get(IDebugService); - const threadId = typeof threadIdArg === 'number' ? threadIdArg : undefined; let thread: IThread | undefined; - if (threadId) { + if (typeof threadId === 'number') { debugService.getModel().getSessions().forEach(s => { if (!thread) { thread = s.getThread(threadId); @@ -105,6 +104,10 @@ function getFrame(debugService: IDebugService, frameId: string | undefined): ISt export function registerCommands(): void { + // These commands are used in call stack context menu, call stack inline actions, command pallete, debug toolbar, mac native touch bar + // When the command is exectued in the context of a thread(context menu on a thread, inline call stack action) we pass the thread id + // Otherwise when it is executed "globaly"(using the touch bar, debug toolbar, command pallete) we do not pass any id and just take whatever is the focussed thread + // Same for stackFrame commands and session commands. CommandsRegistry.registerCommand({ id: COPY_STACK_TRACE_ID, handler: async (accessor: ServicesAccessor, _: string, frameId: string | undefined) => { From 7e57821af24dc167b910bda38d5e14ceb7bbb0b4 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Oct 2019 17:30:48 +0200 Subject: [PATCH 374/435] Terminal and part of the debug changes needed to respond to cancelling a prelaunch task (#82255) Part of #81768 --- .../workbench/contrib/debug/browser/debugService.ts | 12 ++++++++++-- .../workbench/contrib/terminal/browser/terminal.ts | 2 +- .../contrib/terminal/browser/terminalInstance.ts | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index cdef1b6d531..15ed577b5ab 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -780,9 +780,17 @@ export class DebugService implements IDebugService { }); const taskPromise = this.taskService.run(task); if (task.configurationProperties.isBackground) { - return new Promise((c, e) => once(e => e.kind === TaskEventKind.Inactive && e.taskId === task._id, this.taskService.onDidStateChange)(() => { + return new Promise((c, e) => once(e => { + // When a task isBackground it will go inactive when it is safe to launch. + // But when a background task is terminated by the user, it will also fire an inactive event. + // This means that we will not get to see the real exit code from running the task (undefined when terminated by the user). + // Catch the ProcessEnded event here, which occurs before inactive, and capture the exit code to prevent this. + return (e.kind === TaskEventKind.Inactive + || (e.kind === TaskEventKind.ProcessEnded && e.exitCode === undefined)) + && e.taskId === task._id; + }, this.taskService.onDidStateChange)(e => { taskStarted = true; - c(null); + c(e.kind === TaskEventKind.ProcessEnded ? { exitCode: e.exitCode } : null); })); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 1997bdac7ad..c3ede8986ad 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -226,7 +226,7 @@ export interface ITerminalInstance { * is the processes' exit code, an exit code of null means the process was killed as a result of * the ITerminalInstance being disposed. */ - onExit: Event; + onExit: Event; processReady: Promise; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index b9eed7e31ec..ec49836256a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -232,8 +232,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { public get commandTracker(): CommandTrackerAddon | undefined { return this._commandTrackerAddon; } public get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; } - private readonly _onExit = new Emitter(); - public get onExit(): Event { return this._onExit.event; } + private readonly _onExit = new Emitter(); + public get onExit(): Event { return this._onExit.event; } private readonly _onDisposed = new Emitter(); public get onDisposed(): Event { return this._onDisposed.event; } private readonly _onFocused = new Emitter(); @@ -1102,7 +1102,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - this._onExit.fire(exitCode || 0); + this._onExit.fire(exitCode); } private _attachPressAnyKeyToCloseListener(xterm: XTermTerminal) { From d67491f54605069dff8568d53896b8c8409a5822 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 09:14:06 -0700 Subject: [PATCH 375/435] Update color tokens --- .../workbench/browser/parts/activitybar/activitybarActions.ts | 2 +- src/vs/workbench/common/theme.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index dbfbdf0ebc0..062d49bda70 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -288,7 +288,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { } const activeBackgroundColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND); - if (activeForegroundColor) { + if (activeBackgroundColor) { collector.addRule(` .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item { z-index: 0; diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 7dd36c89319..c3cbbf8abdd 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -349,7 +349,7 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { export const ACTIVITY_BAR_ACTIVE_BORDER = registerColor('activityBar.activeBorder', { dark: ACTIVITY_BAR_FOREGROUND, light: ACTIVITY_BAR_FOREGROUND, - hc: transparent(Color.white, 0) + hc: null }, nls.localize('activityBarActiveBorder', "Activity bar border color for the active item. 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_ACTIVE_BACKGROUND = registerColor('activityBar.activeBackground', { From 675c8d8ec43369658a3501dddc020150de88b10c Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 09:15:18 -0700 Subject: [PATCH 376/435] Fix #51816 --- src/vs/workbench/contrib/update/browser/update.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index fd18b8d852b..ed9938dc7dc 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -469,7 +469,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu group: '6_update', command: { id: 'update.restart', - title: nls.localize('restartToUpdate', "Restart to Update") + title: nls.localize('restartToUpdate', "*Restart to Update") }, when: CONTEXT_UPDATE_STATE.isEqualTo(StateType.Ready) }); From e80d909439c2c36dde98ead5ce979947d44fd839 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 18:33:14 +0200 Subject: [PATCH 377/435] scm: don't use ResourceTree model if view mode is List related to #82203 --- src/vs/base/common/resourceTree.ts | 8 +++++ .../contrib/scm/browser/repositoryPanel.ts | 31 ++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/vs/base/common/resourceTree.ts b/src/vs/base/common/resourceTree.ts index 1272d4a6ad0..af53307e036 100644 --- a/src/vs/base/common/resourceTree.ts +++ b/src/vs/base/common/resourceTree.ts @@ -69,6 +69,10 @@ class BranchNode extends Node implements IBranchNode { delete(path: string): void { this._children.delete(path); } + + clear(): void { + this._children.clear(); + } } class LeafNode extends Node implements ILeafNode { @@ -195,4 +199,8 @@ export class ResourceTree, C> { node.delete(name); return child.element; } + + clear(): void { + this.root.clear(); + } } diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index 130e661fff5..c4c1948285c 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -403,6 +403,17 @@ class ViewModel { get mode(): ViewModelMode { return this._mode; } set mode(mode: ViewModelMode) { this._mode = mode; + + for (const item of this.items) { + item.tree.clear(); + + if (mode === ViewModelMode.Tree) { + for (const resource of item.resources) { + item.tree.add(resource.sourceUri, resource); + } + } + } + this.refresh(); this._onDidChangeMode.fire(mode); } @@ -432,10 +443,12 @@ class ViewModel { group.onDidSplice(splice => this.onDidSpliceGroup(item, splice)) ); - const item = { group, resources, tree, disposable }; + const item: IGroupItem = { group, resources, tree, disposable }; - for (const resource of resources) { - item.tree.add(resource.sourceUri, resource); + if (this._mode === ViewModelMode.Tree) { + for (const resource of resources) { + item.tree.add(resource.sourceUri, resource); + } } itemsToInsert.push(item); @@ -451,14 +464,18 @@ class ViewModel { } private onDidSpliceGroup(item: IGroupItem, { start, deleteCount, toInsert }: ISplice): void { - for (const resource of toInsert) { - item.tree.add(resource.sourceUri, resource); + if (this._mode === ViewModelMode.Tree) { + for (const resource of toInsert) { + item.tree.add(resource.sourceUri, resource); + } } const deleted = item.resources.splice(start, deleteCount, ...toInsert); - for (const resource of deleted) { - item.tree.delete(resource.sourceUri); + if (this._mode === ViewModelMode.Tree) { + for (const resource of deleted) { + item.tree.delete(resource.sourceUri); + } } this.refresh(item); From afa911d942f60aff56a65be989eb8c74d9cc56a5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 18:37:28 +0200 Subject: [PATCH 378/435] scm: make tree rendering opt-in via proposed API fix #82203 --- extensions/git/src/repository.ts | 4 +- src/vs/vscode.proposed.d.ts | 29 ++++++++++++ src/vs/workbench/api/browser/mainThreadSCM.ts | 9 ++-- .../workbench/api/common/extHost.api.impl.ts | 4 +- .../workbench/api/common/extHost.protocol.ts | 6 ++- src/vs/workbench/api/common/extHostSCM.ts | 21 +++++++-- .../contrib/scm/browser/repositoryPanel.ts | 46 ++++++++++++------- src/vs/workbench/contrib/scm/common/scm.ts | 1 + 8 files changed, 92 insertions(+), 28 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 416e98ce79a..377851c5bcd 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -691,7 +691,9 @@ export class Repository implements Disposable { this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, onDotGitFileChange, outputChannel)); const root = Uri.file(repository.root); - this._sourceControl = scm.createSourceControl('git', 'Git', root); + this._sourceControl = scm.createSourceControl('git', 'Git', root, { + treeRendering: true + }); this._sourceControl.acceptInputCommand = { command: 'git.commit', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.quickDiffProvider = this; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 93afe709fbb..183148f6570 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -764,6 +764,35 @@ declare module 'vscode' { //#endregion + //#region Joao: SCM tree rendering + + /** + * Options for creating a [SourceControl](#SourceControl) instance. + */ + export interface SourceControlOptions { + + /** + * Whether tree rendering is supported by the [SourceControl](#SourceControl) instance. + */ + readonly treeRendering?: boolean; + } + + export namespace scm { + + /** + * Creates a new [source control](#SourceControl) instance. + * + * @param id An `id` for the source control. Something short, e.g.: `git`. + * @param label A human-readable string for the source control. E.g.: `Git`. + * @param rootUri An optional Uri of the root of the source control. E.g.: `Uri.parse(workspaceRoot)`. + * @param options Additional options for creating the source control. + * @return An instance of [source control](#SourceControl). + */ + export function createSourceControl(id: string, label: string, rootUri?: Uri, options?: SourceControlOptions): SourceControl; + } + + //#endregion + //#region Joao: SCM Input Box /** diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 4488720cf9a..9e9f9ff7dbf 100644 --- a/src/vs/workbench/api/browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/browser/mainThreadSCM.ts @@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { assign } from 'vs/base/common/objects'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm'; -import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol'; +import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMProviderProps, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol'; import { Command } from 'vs/editor/common/modes'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ISplice, Sequence } from 'vs/base/common/sequence'; @@ -128,12 +128,15 @@ class MainThreadSCMProvider implements ISCMProvider { private readonly _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; + get treeRendering(): boolean { return this._props.treeRendering; } + constructor( private readonly proxy: ExtHostSCMShape, private readonly _handle: number, private readonly _contextValue: string, private readonly _label: string, private readonly _rootUri: URI | undefined, + private readonly _props: SCMProviderProps, @ISCMService scmService: ISCMService ) { } @@ -287,8 +290,8 @@ export class MainThreadSCM implements MainThreadSCMShape { this._disposables.dispose(); } - $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void { - const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri && URI.revive(rootUri), this.scmService); + $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined, props: SCMProviderProps): void { + const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri && URI.revive(rootUri), props, this.scmService); const repository = this.scmService.registerSCMProvider(provider); this._repositories.set(handle, repository); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 2e8267a6b26..b01c507517a 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -709,8 +709,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I get inputBox() { return extHostSCM.getLastInputBox(extension)!; // Strict null override - Deprecated api }, - createSourceControl(id: string, label: string, rootUri?: vscode.Uri) { - return extHostSCM.createSourceControl(extension, id, label, rootUri); + createSourceControl(id: string, label: string, rootUri?: vscode.Uri, opts?: vscode.SourceControlOptions) { + return extHostSCM.createSourceControl(extension, id, label, rootUri, opts); } }; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index caf10cba5d5..ca01c32fdb6 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -656,6 +656,10 @@ export interface MainThreadExtensionServiceShape extends IDisposable { $onExtensionHostExit(code: number): void; } +export interface SCMProviderProps { + readonly treeRendering: boolean; +} + export interface SCMProviderFeatures { hasQuickDiffProvider?: boolean; count?: number; @@ -689,7 +693,7 @@ export type SCMRawResourceSplices = [ ]; export interface MainThreadSCMShape extends IDisposable { - $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void; + $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined, props: SCMProviderProps): void; $updateSourceControl(handle: number, features: SCMProviderFeatures): void; $unregisterSourceControl(handle: number): void; diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 6bc3d01ff2c..47db2513d83 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -9,7 +9,7 @@ import { debounce } from 'vs/base/common/decorators'; import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { asPromise } from 'vs/base/common/async'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; -import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto } from './extHost.protocol'; +import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, SCMProviderProps } from './extHost.protocol'; import { sortedDiff, equals } from 'vs/base/common/arrays'; import { comparePaths } from 'vs/base/common/comparers'; import * as vscode from 'vscode'; @@ -452,10 +452,15 @@ class ExtHostSourceControl implements vscode.SourceControl { private _commands: ExtHostCommands, private _id: string, private _label: string, - private _rootUri?: vscode.Uri + private _rootUri: vscode.Uri | undefined, + _props: SCMProviderProps ) { + if (!_extension.enableProposedApi && _props.treeRendering) { + throw new Error(`[${_extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${_extension.identifier.value}`); + } + this._inputBox = new ExtHostSCMInputBox(_extension, this._proxy, this.handle); - this._proxy.$registerSourceControl(this.handle, _id, _label, _rootUri); + this._proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, _props); } private updatedResourceGroups = new Set(); @@ -517,6 +522,12 @@ class ExtHostSourceControl implements vscode.SourceControl { } } +function asProps(options: vscode.SourceControlOptions | undefined): SCMProviderProps { + return { + treeRendering: options && !!options.treeRendering || false + }; +} + export class ExtHostSCM implements ExtHostSCMShape { private static _handlePool: number = 0; @@ -576,11 +587,11 @@ export class ExtHostSCM implements ExtHostSCMShape { }); } - createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined): vscode.SourceControl { + createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined, options?: vscode.SourceControlOptions): vscode.SourceControl { this.logService.trace('ExtHostSCM#createSourceControl', extension.identifier.value, id, label, rootUri); const handle = ExtHostSCM._handlePool++; - const sourceControl = new ExtHostSourceControl(extension, this._proxy, this._commands, id, label, rootUri); + const sourceControl = new ExtHostSourceControl(extension, this._proxy, this._commands, id, label, rootUri, asProps(options)); this._sourceControls.set(handle, sourceControl); const sourceControls = this._sourceControlsByExtension.get(ExtensionIdentifier.toKey(extension.identifier)) || []; diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index c4c1948285c..98590275af1 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -11,7 +11,7 @@ import { IDisposable, Disposable, DisposableStore, combinedDisposable } from 'vs import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet'; import { append, $, addClass, toggleClass, trackFocus, removeClass } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; -import { ISCMRepository, ISCMResourceGroup, ISCMResource, InputValidationType } from 'vs/workbench/contrib/scm/common/scm'; +import { ISCMRepository, ISCMResourceGroup, ISCMResource, InputValidationType, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -36,7 +36,7 @@ import { ThrottledDelayer, disposableTimeout } from 'vs/base/common/async'; import { INotificationService } from 'vs/platform/notification/common/notification'; import * as platform from 'vs/base/common/platform'; import { ITreeNode, ITreeFilter, ITreeSorter, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree'; -import { ISequence, ISplice } from 'vs/base/common/sequence'; +import { ISplice } from 'vs/base/common/sequence'; import { ResourceTree, IBranchNode, INode } from 'vs/base/common/resourceTree'; import { ObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/tree/objectTree'; import { Iterator } from 'vs/base/common/iterator'; @@ -402,6 +402,12 @@ class ViewModel { get mode(): ViewModelMode { return this._mode; } set mode(mode: ViewModelMode) { + mode = this.provider.treeRendering ? mode : ViewModelMode.List; + + if (mode === this._mode) { + return; + } + this._mode = mode; for (const item of this.items) { @@ -425,7 +431,7 @@ class ViewModel { private disposables = new DisposableStore(); constructor( - private groups: ISequence, + private provider: ISCMProvider, private tree: ObjectTree, private _mode: ViewModelMode, @IEditorService protected editorService: IEditorService, @@ -484,8 +490,8 @@ class ViewModel { setVisible(visible: boolean): void { if (visible) { this.visibilityDisposables = new DisposableStore(); - this.groups.onDidSplice(this.onDidSpliceGroups, this, this.visibilityDisposables); - this.onDidSpliceGroups({ start: 0, deleteCount: this.items.length, toInsert: this.groups.elements }); + this.provider.groups.onDidSplice(this.onDidSpliceGroups, this, this.visibilityDisposables); + this.onDidSpliceGroups({ start: 0, deleteCount: this.items.length, toInsert: this.provider.groups.elements }); if (typeof this.scrollTop === 'number') { this.tree.scrollTop = this.scrollTop; @@ -533,8 +539,8 @@ class ViewModel { } // go backwards from last group - for (let i = this.groups.elements.length - 1; i >= 0; i--) { - const group = this.groups.elements[i]; + for (let i = this.provider.groups.elements.length - 1; i >= 0; i--) { + const group = this.provider.groups.elements[i]; for (const resource of group.elements) { if (isEqual(uri, resource.sourceUri)) { @@ -759,19 +765,25 @@ export class RepositoryPanel extends ViewletPanel { this._register(this.tree.onContextMenu(this.onListContextMenu, this)); this._register(this.tree); - let mode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; + let mode: ViewModelMode; - const rootUri = this.repository.provider.rootUri; + if (!this.repository.provider.treeRendering) { + mode = ViewModelMode.List; + } else { + mode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree; - if (typeof rootUri !== 'undefined') { - const storageMode = this.storageService.get(`scm.repository.viewMode:${rootUri.toString()}`, StorageScope.WORKSPACE) as ViewModelMode; + const rootUri = this.repository.provider.rootUri; - if (typeof storageMode === 'string') { - mode = storageMode; + if (typeof rootUri !== 'undefined') { + const storageMode = this.storageService.get(`scm.repository.viewMode:${rootUri.toString()}`, StorageScope.WORKSPACE) as ViewModelMode; + + if (typeof storageMode === 'string') { + mode = storageMode; + } } } - this.viewModel = this.instantiationService.createInstance(ViewModel, this.repository.provider.groups, this.tree, mode); + this.viewModel = this.instantiationService.createInstance(ViewModel, this.repository.provider, this.tree, mode); this._register(this.viewModel); addClass(this.listContainer, 'file-icon-themable-tree'); @@ -781,8 +793,10 @@ export class RepositoryPanel extends ViewletPanel { this._register(this.themeService.onDidFileIconThemeChange(this.updateIndentStyles, this)); this._register(this.viewModel.onDidChangeMode(this.onDidChangeMode, this)); - this.toggleViewModelModeAction = new ToggleViewModeAction(this.viewModel); - this._register(this.toggleViewModelModeAction); + if (this.repository.provider.treeRendering) { + this.toggleViewModelModeAction = new ToggleViewModeAction(this.viewModel); + this._register(this.toggleViewModelModeAction); + } this._register(this.onDidChangeBodyVisibility(this._onDidChangeVisibility, this)); diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index 106a85c5f81..de4979ae7d9 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -62,6 +62,7 @@ export interface ISCMProvider extends IDisposable { readonly acceptInputCommand?: Command; readonly statusBarCommands?: Command[]; readonly onDidChange: Event; + readonly treeRendering: boolean; getOriginalResource(uri: URI): Promise; } From c3e909d5a52561dcabec6742373707e4e2c785a8 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 10 Oct 2019 09:53:51 -0700 Subject: [PATCH 379/435] Separate HTML for selection inner corners from remainder of selection (#82182) * Separate inner corners from remainder of selection Fixes #77777. * code style --- .../viewParts/selections/selections.ts | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index f059e95dbb1..fa2dd722033 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -278,13 +278,17 @@ export class SelectionsOverlay extends DynamicViewOverlay { ); } - private _actualRenderOneSelection(output2: string[], visibleStartLineNumber: number, hasMultipleSelections: boolean, visibleRanges: LineVisibleRangesWithStyle[]): void { - const visibleRangesHaveStyle = (visibleRanges.length > 0 && visibleRanges[0].ranges[0].startStyle); + private _actualRenderOneSelection(output2: [string, string][], visibleStartLineNumber: number, hasMultipleSelections: boolean, visibleRanges: LineVisibleRangesWithStyle[]): void { + if (visibleRanges.length === 0) { + return; + } + + const visibleRangesHaveStyle = !!visibleRanges[0].ranges[0].startStyle; const fullLineHeight = (this._lineHeight).toString(); const reducedLineHeight = (this._lineHeight - 1).toString(); - const firstLineNumber = (visibleRanges.length > 0 ? visibleRanges[0].lineNumber : 0); - const lastLineNumber = (visibleRanges.length > 0 ? visibleRanges[visibleRanges.length - 1].lineNumber : 0); + const firstLineNumber = visibleRanges[0].lineNumber; + const lastLineNumber = visibleRanges[visibleRanges.length - 1].lineNumber; for (let i = 0, len = visibleRanges.length; i < len; i++) { const lineVisibleRanges = visibleRanges[i]; @@ -294,7 +298,8 @@ export class SelectionsOverlay extends DynamicViewOverlay { const lineHeight = hasMultipleSelections ? (lineNumber === lastLineNumber || lineNumber === firstLineNumber ? reducedLineHeight : fullLineHeight) : fullLineHeight; const top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0; - let lineOutput = ''; + let innerCornerOutput = ''; + let restOfSelectionOutput = ''; for (let j = 0, lenJ = lineVisibleRanges.ranges.length; j < lenJ; j++) { const visibleRange = lineVisibleRanges.ranges[j]; @@ -306,7 +311,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { // Reverse rounded corner to the left // First comes the selection (blue layer) - lineOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH); + innerCornerOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH); // Second comes the background (white layer) with inverse border radius let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME; @@ -316,13 +321,13 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (startStyle.bottom === CornerStyle.INTERN) { className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT; } - lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH); + innerCornerOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH); } if (endStyle.top === CornerStyle.INTERN || endStyle.bottom === CornerStyle.INTERN) { // Reverse rounded corner to the right // First comes the selection (blue layer) - lineOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH); + innerCornerOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH); // Second comes the background (white layer) with inverse border radius let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME; @@ -332,7 +337,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (endStyle.bottom === CornerStyle.INTERN) { className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT; } - lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH); + innerCornerOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH); } } @@ -353,22 +358,26 @@ export class SelectionsOverlay extends DynamicViewOverlay { className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT; } } - lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left, visibleRange.width); + restOfSelectionOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left, visibleRange.width); } - output2[lineIndex] += lineOutput; + output2[lineIndex][0] += innerCornerOutput; + output2[lineIndex][1] += restOfSelectionOutput; } } private _previousFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = []; public prepareRender(ctx: RenderingContext): void { - const output: string[] = []; + // Build HTML for inner corners separate from HTML for the the rest of selections, + // as the inner corner HTML can interfere with that of other selections. + // In final render, make sure to place the inner corner HTML before the rest of selection HTML. See issue #77777. + const output: [string, string][] = []; const visibleStartLineNumber = ctx.visibleRange.startLineNumber; const visibleEndLineNumber = ctx.visibleRange.endLineNumber; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { const lineIndex = lineNumber - visibleStartLineNumber; - output[lineIndex] = ''; + output[lineIndex] = ['', '']; } const thisFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = []; @@ -385,7 +394,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { } this._previousFrameVisibleRangesWithStyle = thisFrameVisibleRangesWithStyle; - this._renderResult = output; + this._renderResult = output.map(([internalCorners, restOfSelection]) => internalCorners + restOfSelection); } public render(startLineNumber: number, lineNumber: number): string { From 7816110c15b728afb4429994a1261c0da46e2fa7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 10 Oct 2019 11:05:37 -0700 Subject: [PATCH 380/435] Specify exact icon path for deb desktop Fixes #71942 --- build/gulpfile.vscode.linux.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index 7cbda83c0d8..9d3a7caa07e 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -43,7 +43,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`)) - .pipe(replace('@@ICON@@', product.linuxIconName)) + .pipe(replace('@@ICON@@', `/usr/share/pixmaps/${product.linuxIconName}.png`)) .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol)); const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' }) From 80dc6d1067da9c9f3c8478e5220b96c1ce09780e Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 11:09:45 -0700 Subject: [PATCH 381/435] Show dirty state icon when tabCloseButton is off --- .../browser/parts/editor/media/tabstitlecontrol.css | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index 0c056ced27d..7a7950ed2cd 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -186,7 +186,7 @@ overflow: visible; /* ...but still show the close button on hover, focus and when dirty */ } -.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close { +.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close { display: none; /* hide the close action bar when we are configured to hide it */ } @@ -233,10 +233,7 @@ } .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) { - background-repeat: no-repeat; - background-position-y: center; - background-position-x: calc(100% - 6px); /* to the right of the tab label */ - padding-right: 28px; /* make room for dirty indication when we are running without close button */ + padding-right: 0; /* remove extra padding when we are running without close button */ } /* Editor Actions */ From b1190cb5d04314b2f5a9b09b192876a64ad8178f Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 11:39:24 -0700 Subject: [PATCH 382/435] Don't allow dirty state button to be clicked when running without close button --- .../workbench/browser/parts/editor/media/tabstitlecontrol.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index 7a7950ed2cd..532c3378244 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -236,6 +236,10 @@ padding-right: 0; /* remove extra padding when we are running without close button */ } +.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close { + pointer-events: none; /* don't allow dirty state/close button to be clicked when running without close button */ +} + /* Editor Actions */ .monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions { From e8d9892d20f4651280526985fe5272ed7cbd746f Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Thu, 10 Oct 2019 11:59:54 -0700 Subject: [PATCH 383/435] panel pref dimensions fixes #82018 --- src/vs/workbench/browser/parts/panel/panelPart.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 43b7f72a1ca..f9a66d07a6b 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -60,13 +60,13 @@ export class PanelPart extends CompositePart implements IPanelService { readonly snap = true; get preferredHeight(): number | undefined { - const sidebarDimension = assertIsDefined(this.layoutService.getDimension(Parts.SIDEBAR_PART)); - return sidebarDimension.height * 0.4; + // Don't worry about titlebar or statusbar visibility + // The difference is minimal and keeps this function clean + return this.layoutService.dimension.height * 0.4; } get preferredWidth(): number | undefined { - const statusbarDimension = assertIsDefined(this.layoutService.getDimension(Parts.STATUSBAR_PART)); - return statusbarDimension.width * 0.4; + return this.layoutService.dimension.width * 0.4; } //#endregion From 346416d6c28acb88c7698ccec857e5a206830a0a Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Thu, 10 Oct 2019 12:10:20 -0700 Subject: [PATCH 384/435] only left click on menubar fixes #81954 --- src/vs/base/browser/ui/menu/menubar.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index 3d3b3e5cb57..379da40e348 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -20,6 +20,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { asArray } from 'vs/base/common/arrays'; import { ScanCodeUtils, ScanCode } from 'vs/base/common/scanCode'; import { isMacintosh } from 'vs/base/common/platform'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; const $ = DOM.$; @@ -252,7 +253,14 @@ export class MenuBar extends Disposable { e.stopPropagation(); })); - this._register(DOM.addDisposableListener(buttonElement, DOM.EventType.MOUSE_DOWN, (e) => { + this._register(DOM.addDisposableListener(buttonElement, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { + // Ignore non-left-click + const mouseEvent = new StandardMouseEvent(e); + if (!mouseEvent.leftButton) { + e.preventDefault(); + return; + } + if (!this.isOpen) { // Open the menu with mouse down and ignore the following mouse up event this.ignoreNextMouseUp = true; @@ -337,6 +345,13 @@ export class MenuBar extends Disposable { })); this._register(DOM.addDisposableListener(buttonElement, DOM.EventType.MOUSE_DOWN, (e) => { + // Ignore non-left-click + const mouseEvent = new StandardMouseEvent(e); + if (!mouseEvent.leftButton) { + e.preventDefault(); + return; + } + if (!this.isOpen) { // Open the menu with mouse down and ignore the following mouse up event this.ignoreNextMouseUp = true; From 41db44ff34749b1116e164018dbf10af971b8d13 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 12:19:28 -0700 Subject: [PATCH 385/435] Fix #68453 --- src/vs/workbench/common/theme.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index fc41153b077..e789ab0ca66 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -235,8 +235,8 @@ export const PANEL_INACTIVE_TITLE_FOREGROUND = registerColor('panelTitle.inactiv }, nls.localize('panelInactiveTitleForeground', "Title color for the inactive panel. Panels are shown below the editor area and contain views like output and integrated terminal.")); export const PANEL_ACTIVE_TITLE_BORDER = registerColor('panelTitle.activeBorder', { - dark: PANEL_BORDER, - light: PANEL_BORDER, + dark: PANEL_ACTIVE_TITLE_FOREGROUND, + light: PANEL_ACTIVE_TITLE_FOREGROUND, 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.")); From 23956cc5e22616a90e01fa639d12b920ea77566d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Oct 2019 21:26:28 +0200 Subject: [PATCH 386/435] update to electron 6.0.x (#81644) * update to electron 6.0.x * chore: bump electron@6.0.12 --- .yarnrc | 2 +- cgmanifest.json | 12 +- remote/.yarnrc | 2 +- resources/linux/code-url-handler.desktop | 2 +- resources/linux/code.desktop | 4 +- scripts/test-integration.sh | 2 +- scripts/test.sh | 2 +- src/bootstrap.js | 18 +- src/main.js | 7 +- src/typings/electron.d.ts | 1761 ++++++++++++----- .../contextmenu/electron-main/contextmenu.ts | 2 +- src/vs/code/electron-main/app.ts | 2 +- src/vs/code/electron-main/window.ts | 2 +- src/vs/code/node/cli.ts | 6 +- .../platform/dialogs/electron-main/dialogs.ts | 52 +- src/vs/platform/dialogs/node/dialogs.ts | 13 - .../electron-main/electronMainService.ts | 4 +- src/vs/platform/electron/node/electron.ts | 4 +- .../issue/electron-main/issueMainService.ts | 2 +- .../launch/electron-main/launchMainService.ts | 2 +- .../platform/menubar/electron-main/menubar.ts | 4 +- .../runtimeExtensionsEditor.ts | 2 +- .../electron-browser/pre/electron-index.js | 9 - .../electron-browser/fileDialogService.ts | 4 +- .../workbench/test/workbenchTestServices.ts | 14 +- test/electron/index.js | 15 +- 26 files changed, 1394 insertions(+), 555 deletions(-) diff --git a/.yarnrc b/.yarnrc index ff946c7a250..c54f7d6d6e3 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "4.2.10" +target "6.0.12" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index c16d88b5991..c45dca3ef5c 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "c6a08e5368de4352903e702cde750b33239a50ab" + "commitHash": "91f08db83c2ce8c722ddf0911ead8f7c473bedfa" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "69.0.3497.128" + "version": "76.0.3809.146" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b" + "commitHash": "64219741218aa87e259cf8257596073b8e747f0a" } }, "isOnlyProductionDependency": true, - "version": "10.11.0" + "version": "12.4.0" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "4e4c7527c63fcf27dffaeb58bde996b8d859c0ed" + "commitHash": "1e50380fab37f407c4d357e1e30ecbc3d5a703b8" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "4.2.10" + "version": "6.0.12" }, { "component": { diff --git a/remote/.yarnrc b/remote/.yarnrc index b28191e6bae..1e16cde724c 100644 --- a/remote/.yarnrc +++ b/remote/.yarnrc @@ -1,3 +1,3 @@ disturl "http://nodejs.org/dist" -target "10.11.0" +target "12.4.0" runtime "node" diff --git a/resources/linux/code-url-handler.desktop b/resources/linux/code-url-handler.desktop index 7106e0e0969..b85525fbd04 100644 --- a/resources/linux/code-url-handler.desktop +++ b/resources/linux/code-url-handler.desktop @@ -2,7 +2,7 @@ Name=@@NAME_LONG@@ - URL Handler Comment=Code Editing. Redefined. GenericName=Text Editor -Exec=@@EXEC@@ --open-url %U +Exec=@@EXEC@@ --no-sandbox --open-url %U Icon=@@ICON@@ Type=Application NoDisplay=true diff --git a/resources/linux/code.desktop b/resources/linux/code.desktop index 1273bb2db7c..b975e1094a2 100644 --- a/resources/linux/code.desktop +++ b/resources/linux/code.desktop @@ -2,7 +2,7 @@ Name=@@NAME_LONG@@ Comment=Code Editing. Redefined. GenericName=Text Editor -Exec=@@EXEC@@ --unity-launch %F +Exec=@@EXEC@@ --no-sandbox --unity-launch %F Icon=@@ICON@@ Type=Application StartupNotify=false @@ -14,5 +14,5 @@ Keywords=vscode; [Desktop Action new-empty-window] Name=New Empty Window -Exec=@@EXEC@@ --new-window %F +Exec=@@EXEC@@ --no-sandbox --new-window %F Icon=@@ICON@@ diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index a3891cf96fc..21652b632cf 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -8,7 +8,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then else ROOT=$(dirname $(dirname $(readlink -f $0))) VSCODEUSERDATADIR=`mktemp -d 2>/dev/null` - LINUX_NO_SANDBOX="" + LINUX_NO_SANDBOX="--no-sandbox" # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. fi cd $ROOT diff --git a/scripts/test.sh b/scripts/test.sh index e1ed5aa65c7..630af4e53e5 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -34,5 +34,5 @@ else cd $ROOT ; \ ELECTRON_ENABLE_LOGGING=1 \ "$CODE" \ - test/electron/index.js "$@" + test/electron/index.js --no-sandbox "$@" # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. fi diff --git a/src/bootstrap.js b/src/bootstrap.js index 3aeaa72e3b1..bd1aa29cebe 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -21,6 +21,7 @@ process.on('SIGPIPE', () => { //#endregion //#region Add support for redirecting the loading of node modules + exports.injectNodeModuleLookupPath = function (injectPath) { if (!injectPath) { throw new Error('Missing injectPath'); @@ -36,10 +37,8 @@ exports.injectNodeModuleLookupPath = function (injectPath) { const originalResolveLookupPaths = Module._resolveLookupPaths; // @ts-ignore - Module._resolveLookupPaths = function (moduleName, parent, newReturn) { - const result = originalResolveLookupPaths(moduleName, parent, newReturn); - - const paths = newReturn ? result : result[1]; + Module._resolveLookupPaths = function (moduleName, parent) { + const paths = originalResolveLookupPaths(moduleName, parent); for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === nodeModulesPath) { paths.splice(i, 0, injectPath); @@ -47,7 +46,7 @@ exports.injectNodeModuleLookupPath = function (injectPath) { } } - return result; + return paths; }; }; //#endregion @@ -71,11 +70,10 @@ exports.enableASARSupport = function (nodeModulesPath) { // @ts-ignore const originalResolveLookupPaths = Module._resolveLookupPaths; - // @ts-ignore - Module._resolveLookupPaths = function (request, parent, newReturn) { - const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = newReturn ? result : result[1]; + // @ts-ignore + Module._resolveLookupPaths = function (request, parent) { + const paths = originalResolveLookupPaths(request, parent); for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); @@ -83,7 +81,7 @@ exports.enableASARSupport = function (nodeModulesPath) { } } - return result; + return paths; }; }; //#endregion diff --git a/src/main.js b/src/main.js index a96b411bf8b..afe479d6174 100644 --- a/src/main.js +++ b/src/main.js @@ -19,7 +19,7 @@ const paths = require('./paths'); // @ts-ignore const product = require('../product.json'); // @ts-ignore -const app = require('electron').app; +const { app, protocol } = require('electron'); // Enable portable support const portable = bootstrap.configurePortable(); @@ -35,6 +35,11 @@ app.setPath('userData', userDataPath); // Update cwd based on environment and platform setCurrentWorkingDirectory(); +// Register custom schemes with privileges +protocol.registerSchemesAsPrivileged([ + { scheme: 'vscode-resource', privileges: { secure: true, supportFetchAPI: true, corsEnabled: true } } +]); + // Global app listeners registerListeners(); diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index 6f44785756c..f1d41613b51 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Electron 4.2.10 +// Type definitions for Electron 6.0.12 // Project: http://electronjs.org/ // Definitions by: The Electron Team // Definitions: https://github.com/electron/electron-typescript-definitions @@ -8,6 +8,7 @@ type GlobalEvent = Event; declare namespace Electron { + // TODO: Replace this declaration with NodeJS.EventEmitter class EventEmitter { addListener(event: string, listener: Function): this; on(event: string, listener: Function): this; @@ -21,28 +22,17 @@ declare namespace Electron { listenerCount(type: string): number; prependListener(event: string, listener: Function): this; prependOnceListener(event: string, listener: Function): this; - eventNames(): string[]; + eventNames(): Array<(string | symbol)>; } class Accelerator extends String { } - interface Event extends GlobalEvent { - preventDefault: () => void; - sender: WebContents; - returnValue: any; - ctrlKey?: boolean; - metaKey?: boolean; - shiftKey?: boolean; - altKey?: boolean; - } - interface CommonInterface { clipboard: Clipboard; crashReporter: CrashReporter; nativeImage: typeof NativeImage; - screen: Screen; shell: Shell; } @@ -69,6 +59,7 @@ declare namespace Electron { powerMonitor: PowerMonitor; powerSaveBlocker: PowerSaveBlocker; protocol: Protocol; + screen: Screen; session: typeof Session; systemPreferences: SystemPreferences; TouchBar: typeof TouchBar; @@ -203,9 +194,9 @@ declare namespace Electron { userInfo: any) => void): this; /** * Emitted before the application starts closing its windows. Calling - * event.preventDefault() will prevent the default behaviour, which is terminating + * event.preventDefault() will prevent the default behavior, which is terminating * the application. Note: If application quit was initiated by - * autoUpdater.quitAndInstall() then before-quit is emitted after emitting close + * autoUpdater.quitAndInstall(), then before-quit is emitted after emitting close * event on all windows and closing them. Note: On Windows, this event will not be * emitted if the app is closed due to a shutdown/restart of the system or a user * logout. @@ -372,6 +363,18 @@ declare namespace Electron { * A string with the error's localized description. */ error: string) => void): this; + /** + * Emitted when desktopCapturer.getSources() is called in the renderer process of + * webContents. Calling event.preventDefault() will make it return empty sources. + */ + on(event: 'desktop-capturer-get-sources', listener: (event: Event, + webContents: WebContents) => void): this; + once(event: 'desktop-capturer-get-sources', listener: (event: Event, + webContents: WebContents) => void): this; + addListener(event: 'desktop-capturer-get-sources', listener: (event: Event, + webContents: WebContents) => void): this; + removeListener(event: 'desktop-capturer-get-sources', listener: (event: Event, + webContents: WebContents) => void): this; /** * Emitted when the gpu process crashes or is killed. */ @@ -385,7 +388,7 @@ declare namespace Electron { killed: boolean) => void): this; /** * Emitted when webContents wants to do basic auth. The default behavior is to - * cancel all authentications, to override this you should prevent the default + * cancel all authentications. To override this you should prevent the default * behavior with event.preventDefault() and call callback(username, password) with * the credentials. */ @@ -566,13 +569,30 @@ declare namespace Electron { removeListener(event: 'remote-require', listener: (event: Event, webContents: WebContents, moduleName: string) => void): this; + /** + * Emitted when the renderer process of webContents crashes or is killed. + */ + on(event: 'renderer-process-crashed', listener: (event: Event, + webContents: WebContents, + killed: boolean) => void): this; + once(event: 'renderer-process-crashed', listener: (event: Event, + webContents: WebContents, + killed: boolean) => void): this; + addListener(event: 'renderer-process-crashed', listener: (event: Event, + webContents: WebContents, + killed: boolean) => void): this; + removeListener(event: 'renderer-process-crashed', listener: (event: Event, + webContents: WebContents, + killed: boolean) => void): this; /** * This event will be emitted inside the primary instance of your application when - * a second instance has been executed. argv is an Array of the second instance's - * command line arguments, and workingDirectory is its current working directory. - * Usually applications respond to this by making their primary window focused and - * non-minimized. This event is guaranteed to be emitted after the ready event of - * app gets emitted. + * a second instance has been executed and calls app.requestSingleInstanceLock(). + * argv is an Array of the second instance's command line arguments, and + * workingDirectory is its current working directory. Usually applications respond + * to this by making their primary window focused and non-minimized. This event is + * guaranteed to be emitted after the ready event of app gets emitted. Note: Extra + * command line arguments might be added by Chromium, such as + * --original-process-start-time. */ on(event: 'second-instance', listener: (event: Event, /** @@ -647,8 +667,8 @@ declare namespace Electron { * Emitted when Handoff is about to be resumed on another device. If you need to * update the state to be transferred, you should call event.preventDefault() * immediately, construct a new userInfo dictionary and call - * app.updateCurrentActiviy() in a timely manner. Otherwise the operation will fail - * and continue-activity-error will be called. + * app.updateCurrentActiviy() in a timely manner. Otherwise, the operation will + * fail and continue-activity-error will be called. */ on(event: 'update-activity-state', listener: (event: Event, /** @@ -760,8 +780,8 @@ declare namespace Electron { removeListener(event: 'window-all-closed', listener: Function): this; /** * Adds path to the recent documents list. This list is managed by the OS. On - * Windows you can visit the list from the task bar, and on macOS you can visit it - * from dock menu. + * Windows, you can visit the list from the task bar, and on macOS, you can visit + * it from dock menu. */ addRecentDocument(path: string): void; /** @@ -779,11 +799,6 @@ declare namespace Electron { * before app is ready. */ disableHardwareAcceleration(): void; - /** - * Enables mixed sandbox mode on the app. This method can only be called before app - * is ready. - */ - enableMixedSandbox(): void; /** * Enables full sandbox mode on the app. This method can only be called before app * is ready. @@ -791,8 +806,8 @@ declare namespace Electron { enableSandbox(): void; /** * Exits immediately with exitCode. exitCode defaults to 0. All windows will be - * closed immediately without asking user and the before-quit and will-quit events - * will not be emitted. + * closed immediately without asking the user, and the before-quit and will-quit + * events will not be emitted. */ exit(exitCode?: number): void; /** @@ -808,12 +823,19 @@ declare namespace Electron { * Fetches a path's associated icon. On Windows, there a 2 kinds of icons: On Linux * and macOS, icons depend on the application associated with file mime type. */ - getFileIcon(path: string, callback: (error: Error, icon: NativeImage) => void): void; + getFileIcon(path: string, options?: FileIconOptions): Promise; /** - * Fetches a path's associated icon. On Windows, there a 2 kinds of icons: On Linux - * and macOS, icons depend on the application associated with file mime type. + * Fetches a path's associated icon. On Windows, there are 2 kinds of icons: On + * Linux and macOS, icons depend on the application associated with file mime type. + * Deprecated Soon */ getFileIcon(path: string, options: FileIconOptions, callback: (error: Error, icon: NativeImage) => void): void; + /** + * Fetches a path's associated icon. On Windows, there are 2 kinds of icons: On + * Linux and macOS, icons depend on the application associated with file mime type. + * Deprecated Soon + */ + getFileIcon(path: string, callback: (error: Error, icon: NativeImage) => void): void; getGPUFeatureStatus(): GPUFeatureStatus; /** * For infoType equal to complete: Promise is fulfilled with Object containing all @@ -828,12 +850,16 @@ declare namespace Electron { /** * To set the locale, you'll want to use a command line switch at app startup, * which may be found here. Note: When distributing your packaged app, you have to - * also ship the locales folder. Note: On Windows you have to call it after the + * also ship the locales folder. Note: On Windows, you have to call it after the * ready events gets emitted. */ getLocale(): string; /** - * If you provided path and args options to app.setLoginItemSettings then you need + * Note: When unable to detect locale country code, it returns empty string. + */ + getLocaleCountryCode(): string; + /** + * If you provided path and args options to app.setLoginItemSettings, then you need * to pass the same arguments here for openAtLogin to be set correctly. */ getLoginItemSettings(options?: LoginItemSettingsOptions): LoginItemSettings; @@ -870,6 +896,9 @@ declare namespace Electron { * Invalidates the current Handoff user activity. */ invalidateCurrentActivity(type: string): void; + /** + * Deprecated Soon + */ isAccessibilitySupportEnabled(): boolean; /** * This method checks if the current executable is the default handler for a @@ -881,15 +910,16 @@ declare namespace Electron { * the Windows Registry and LSCopyDefaultHandlerForURLScheme internally. */ isDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; + isEmojiPanelSupported(): boolean; isInApplicationsFolder(): boolean; isReady(): boolean; isUnityRunning(): boolean; /** - * No confirmation dialog will be presented by default, if you wish to allow the - * user to confirm the operation you may do so using the dialog API. NOTE: This + * No confirmation dialog will be presented by default. If you wish to allow the + * user to confirm the operation, you may do so using the dialog API. NOTE: This * method throws errors if anything other than the user causes the move to fail. - * For instance if the user cancels the authorization dialog this method returns - * false. If we fail to perform the copy then this method will throw an error. The + * For instance if the user cancels the authorization dialog, this method returns + * false. If we fail to perform the copy, then this method will throw an error. The * message in the error should be informative and tell you exactly what went wrong */ moveToApplicationsFolder(): boolean; @@ -903,14 +933,14 @@ declare namespace Electron { */ quit(): void; /** - * Relaunches the app when current instance exits. By default the new instance will - * use the same working directory and command line arguments with current instance. - * When args is specified, the args will be passed as command line arguments - * instead. When execPath is specified, the execPath will be executed for relaunch - * instead of current app. Note that this method does not quit the app when - * executed, you have to call app.quit or app.exit after calling app.relaunch to - * make the app restart. When app.relaunch is called for multiple times, multiple - * instances will be started after current instance exited. An example of + * Relaunches the app when current instance exits. By default, the new instance + * will use the same working directory and command line arguments with current + * instance. When args is specified, the args will be passed as command line + * arguments instead. When execPath is specified, the execPath will be executed for + * relaunch instead of current app. Note that this method does not quit the app + * when executed, you have to call app.quit or app.exit after calling app.relaunch + * to make the app restart. When app.relaunch is called for multiple times, + * multiple instances will be started after current instance exited. An example of * restarting current instance immediately and adding a new command line argument * to the new instance: */ @@ -926,27 +956,25 @@ declare namespace Electron { */ removeAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** - * This method makes your application a Single Instance Application - instead of - * allowing multiple instances of your app to run, this will ensure that only a - * single instance of your app is running, and other instances signal this instance - * and exit. The return value of this method indicates whether or not this instance - * of your application successfully obtained the lock. If it failed to obtain the - * lock you can assume that another instance of your application is already running - * with the lock and exit immediately. I.e. This method returns true if your - * process is the primary instance of your application and your app should continue - * loading. It returns false if your process should immediately quit as it has - * sent its parameters to another instance that has already acquired the lock. On - * macOS the system enforces single instance automatically when users try to open a - * second instance of your app in Finder, and the open-file and open-url events - * will be emitted for that. However when users start your app in command line the - * system's single instance mechanism will be bypassed and you have to use this + * The return value of this method indicates whether or not this instance of your + * application successfully obtained the lock. If it failed to obtain the lock, + * you can assume that another instance of your application is already running with + * the lock and exit immediately. I.e. This method returns true if your process is + * the primary instance of your application and your app should continue loading. + * It returns false if your process should immediately quit as it has sent its + * parameters to another instance that has already acquired the lock. On macOS, the + * system enforces single instance automatically when users try to open a second + * instance of your app in Finder, and the open-file and open-url events will be + * emitted for that. However when users start your app in command line, the + * system's single instance mechanism will be bypassed, and you have to use this * method to ensure single instance. An example of activating the window of primary * instance when a second instance starts: */ requestSingleInstanceLock(): boolean; /** * Set the about panel options. This will override the values defined in the app's - * .plist file. See the Apple docs for more details. + * .plist file on MacOS. See the Apple docs for more details. On Linux, values must + * be set in order to be shown; there are no defaults. */ setAboutPanelOptions(options: AboutPanelOptionsOptions): void; /** @@ -955,9 +983,17 @@ declare namespace Electron { * accessibility docs for more details. Disabled by default. This API must be * called after the ready event is emitted. Note: Rendering accessibility tree can * significantly affect the performance of your app. It should not be enabled by - * default. + * default. Deprecated Soon */ setAccessibilitySupportEnabled(enabled: boolean): void; + /** + * Sets or creates a directory your app's logs which can then be manipulated with + * app.getPath() or app.setPath(pathName, newPath). Calling app.setAppLogsPath() + * without a path parameter will result in this directory being set to + * /Library/Logs/YourAppName on macOS, and inside the userData directory on Linux + * and Windows. + */ + setAppLogsPath(path?: string): void; /** * Changes the Application User Model ID to id. */ @@ -967,20 +1003,23 @@ declare namespace Electron { * (aka URI scheme). It allows you to integrate your app deeper into the operating * system. Once registered, all links with your-protocol:// will be opened with the * current executable. The whole link, including protocol, will be passed to your - * application as a parameter. On Windows you can provide optional parameters path, - * the path to your executable, and args, an array of arguments to be passed to - * your executable when it launches. Note: On macOS, you can only register + * application as a parameter. On Windows, you can provide optional parameters + * path, the path to your executable, and args, an array of arguments to be passed + * to your executable when it launches. Note: On macOS, you can only register * protocols that have been added to your app's info.plist, which can not be * modified at runtime. You can however change the file with a simple text editor * or script during build time. Please refer to Apple's documentation for details. - * The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme - * internally. + * Note: In a Windows Store environment (when packaged as an appx) this API will + * return true for all calls but the registry key it sets won't be accessible by + * other applications. In order to register your Windows Store application as a + * default protocol handler you must declare the protocol in your manifest. The API + * uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally. */ setAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** * Sets the counter badge for current app. Setting the count to 0 will hide the - * badge. On macOS it shows on the dock icon. On Linux it only works for Unity - * launcher, Note: Unity launcher requires the existence of a .desktop file to + * badge. On macOS, it shows on the dock icon. On Linux, it only works for Unity + * launcher. Note: Unity launcher requires the existence of a .desktop file to * work, for more information please read Desktop Environment Integration. */ setBadgeCount(count: number): boolean; @@ -1012,12 +1051,12 @@ declare namespace Electron { setName(name: string): void; /** * Overrides the path to a special directory or file associated with name. If the - * path specifies a directory that does not exist, the directory will be created by - * this method. On failure an Error is thrown. You can only override paths of a - * name defined in app.getPath. By default, web pages' cookies and caches will be - * stored under the userData directory. If you want to change this location, you - * have to override the userData path before the ready event of the app module is - * emitted. + * path specifies a directory that does not exist, an Error is thrown. In that + * case, the directory should be created with fs.mkdirSync or similar. You can only + * override paths of a name defined in app.getPath. By default, web pages' cookies + * and caches will be stored under the userData directory. If you want to change + * this location, you have to override the userData path before the ready event of + * the app module is emitted. */ setPath(name: string, path: string): void; /** @@ -1037,10 +1076,14 @@ declare namespace Electron { */ show(): void; /** - * Show the about panel with the values defined in the app's .plist file or with - * the options set via app.setAboutPanelOptions(options). + * Show the app's about panel options. These options can be overridden with + * app.setAboutPanelOptions(options). */ showAboutPanel(): void; + /** + * Show the platform's native emoji picker. + */ + showEmojiPanel(): void; /** * Start accessing a security scoped resource. With this method Electron * applications that are packaged for the Mac App Store may reach outside their @@ -1054,6 +1097,34 @@ declare namespace Electron { */ updateCurrentActivity(type: string, userInfo: any): void; whenReady(): Promise; + /** + * A Boolean property that's true if Chrome's accessibility support is enabled, + * false otherwise. This property will be true if the use of assistive + * technologies, such as screen readers, has been detected. Setting this property + * to true manually enables Chrome's accessibility support, allowing developers to + * expose accessibility switch to users in application settings. See Chromium's + * accessibility docs for more details. Disabled by default. This API must be + * called after the ready event is emitted. Note: Rendering accessibility tree can + * significantly affect the performance of your app. It should not be enabled by + * default. + */ + accessibilitySupportEnabled?: boolean; + /** + * A Boolean which when true disables the overrides that Electron has in place to + * ensure renderer processes are restarted on every navigation. The current + * default value for this property is false. The intention is for these overrides + * to become disabled by default and then at some point in the future this property + * will be removed. This property impacts which native modules you can use in the + * renderer process. For more information on the direction Electron is going with + * renderer process restarts and usage of native modules in the renderer process + * please check out this Tracking Issue. + */ + allowRendererProcessReuse?: boolean; + /** + * A Menu property that return Menu if one has been set and null otherwise. Users + * can pass a Menu to set this property. + */ + applicationMenu?: Menu; commandLine: CommandLine; dock: Dock; /** @@ -1217,7 +1288,8 @@ declare namespace Electron { * media keys or browser commands, as well as the "Back" button built into some * mice on Windows. Commands are lowercased, underscores are replaced with hyphens, * and the APPCOMMAND_ prefix is stripped off. e.g. APPCOMMAND_BROWSER_BACKWARD is - * emitted as browser-backward. + * emitted as browser-backward. The following app commands are explictly supported + * on Linux: */ on(event: 'app-command', listener: (event: Event, command: string) => void): this; @@ -1551,6 +1623,10 @@ declare namespace Electron { * ready event of the app module is emitted. */ static removeExtension(name: string): void; + /** + * Replacement API for setBrowserView supporting work with multi browser views. + */ + addBrowserView(browserView: BrowserView): void; /** * Adds a window as a tab on this window, after the tab for the window instance. */ @@ -1561,11 +1637,22 @@ declare namespace Electron { blur(): void; blurWebView(): void; /** - * Same as webContents.capturePage([rect, ]callback). + * Captures a snapshot of the page within rect. Upon completion callback will be + * called with callback(image). The image is an instance of NativeImage that stores + * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(callback: (image: NativeImage) => void): void; /** - * Same as webContents.capturePage([rect, ]callback). + * Captures a snapshot of the page within rect. Omitting rect will capture the + * whole visible page. + */ + capturePage(rect?: Rectangle): Promise; + /** + * Captures a snapshot of the page within rect. Upon completion callback will be + * called with callback(image). The image is an instance of NativeImage that stores + * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** @@ -1598,11 +1685,13 @@ declare namespace Electron { focus(): void; focusOnWebView(): void; getBounds(): Rectangle; - /** - * Note: The BrowserView API is currently experimental and may change or be removed - * in future Electron releases. - */ getBrowserView(): (BrowserView) | (null); + /** + * Returns array of BrowserView what was an attached with addBrowserView or + * setBrowserView. Note: The BrowserView API is currently experimental and may + * change or be removed in future Electron releases. + */ + getBrowserViews(): void; getChildWindows(): BrowserWindow[]; getContentBounds(): Rectangle; getContentSize(): number[]; @@ -1626,13 +1715,10 @@ declare namespace Electron { getRepresentedFilename(): string; getSize(): number[]; /** - * Note: The title of web page can be different from the title of the native + * Note: The title of the web page can be different from the title of the native * window. */ getTitle(): string; - /** - * On Windows and Linux always returns true. - */ hasShadow(): boolean; /** * Hides the window. @@ -1684,7 +1770,7 @@ declare namespace Electron { * Same as webContents.loadFile, filePath should be a path to an HTML file relative * to the root of your application. See the webContents docs for more information. */ - loadFile(filePath: string, options?: LoadFileOptions): void; + loadFile(filePath: string, options?: LoadFileOptions): Promise; /** * Same as webContents.loadURL(url[, options]). The url can be a remote address * (e.g. http://) or a path to a local HTML file using the file:// protocol. To @@ -1692,7 +1778,7 @@ declare namespace Electron { * url.format method: You can load a URL using a POST request with URL-encoded data * by doing the following: */ - loadURL(url: string, options?: LoadURLOptions): void; + loadURL(url: string, options?: LoadURLOptions): Promise; /** * Maximizes the window. This will also show (but not focus) the window if it isn't * being displayed already. @@ -1725,6 +1811,11 @@ declare namespace Electron { * Same as webContents.reload. */ reload(): void; + removeBrowserView(browserView: BrowserView): void; + /** + * Remove the window's menu bar. + */ + removeMenu(): void; /** * Restores the window from minimized state to its previous state. */ @@ -1829,7 +1920,7 @@ declare namespace Electron { */ setFullScreenable(fullscreenable: boolean): void; /** - * Sets whether the window should have a shadow. On Windows and Linux does nothing. + * Sets whether the window should have a shadow. */ setHasShadow(hasShadow: boolean): void; /** @@ -1856,8 +1947,7 @@ declare namespace Electron { */ setMaximumSize(width: number, height: number): void; /** - * Sets the menu as the window's menu bar, setting it to null will remove the menu - * bar. + * Sets the menu as the window's menu bar. */ setMenu(menu: (Menu) | (null)): void; /** @@ -2296,12 +2386,12 @@ declare namespace Electron { // Docs: http://electronjs.org/docs/api/clipboard - availableFormats(type?: string): string[]; + availableFormats(type?: 'selection' | 'clipboard'): string[]; /** * Clears the clipboard content. */ - clear(type?: string): void; - has(format: string, type?: string): boolean; + clear(type?: 'selection' | 'clipboard'): void; + has(format: string, type?: 'selection' | 'clipboard'): boolean; read(format: string): string; /** * Returns an Object containing title and url keys representing the bookmark in the @@ -2310,93 +2400,94 @@ declare namespace Electron { */ readBookmark(): ReadBookmark; readBuffer(format: string): Buffer; + /** + * This method uses synchronous IPC when called from the renderer process. The + * cached value is reread from the find pasteboard whenever the application is + * activated. + */ readFindText(): string; - readHTML(type?: string): string; - readImage(type?: string): NativeImage; - readRTF(type?: string): string; - readText(type?: string): string; + readHTML(type?: 'selection' | 'clipboard'): string; + readImage(type?: 'selection' | 'clipboard'): NativeImage; + readRTF(type?: 'selection' | 'clipboard'): string; + readText(type?: 'selection' | 'clipboard'): string; /** * Writes data to the clipboard. */ - write(data: Data, type?: string): void; + write(data: Data, type?: 'selection' | 'clipboard'): void; /** * Writes the title and url into the clipboard as a bookmark. Note: Most apps on * Windows don't support pasting bookmarks into them so you can use clipboard.write * to write both a bookmark and fallback text to the clipboard. */ - writeBookmark(title: string, url: string, type?: string): void; + writeBookmark(title: string, url: string, type?: 'selection' | 'clipboard'): void; /** * Writes the buffer into the clipboard as format. */ - writeBuffer(format: string, buffer: Buffer, type?: string): void; + writeBuffer(format: string, buffer: Buffer, type?: 'selection' | 'clipboard'): void; /** - * Writes the text into the find pasteboard as plain text. This method uses - * synchronous IPC when called from the renderer process. + * Writes the text into the find pasteboard (the pasteboard that holds information + * about the current state of the active application’s find panel) as plain text. + * This method uses synchronous IPC when called from the renderer process. */ writeFindText(text: string): void; /** * Writes markup to the clipboard. */ - writeHTML(markup: string, type?: string): void; + writeHTML(markup: string, type?: 'selection' | 'clipboard'): void; /** * Writes image to the clipboard. */ - writeImage(image: NativeImage, type?: string): void; + writeImage(image: NativeImage, type?: 'selection' | 'clipboard'): void; /** * Writes the text into the clipboard in RTF. */ - writeRTF(text: string, type?: string): void; + writeRTF(text: string, type?: 'selection' | 'clipboard'): void; /** * Writes the text into the clipboard as plain text. */ - writeText(text: string, type?: string): void; + writeText(text: string, type?: 'selection' | 'clipboard'): void; } interface ContentTracing extends EventEmitter { // Docs: http://electronjs.org/docs/api/content-tracing - /** - * Get the current monitoring traced data. Child processes typically cache trace - * data and only rarely flush and send trace data back to the main process. This is - * because it may be an expensive operation to send the trace data over IPC and we - * would like to avoid unneeded runtime overhead from tracing. So, to end tracing, - * we must asynchronously ask all child processes to flush any pending trace data. - * Once all child processes have acknowledged the captureMonitoringSnapshot request - * the callback will be called with a file that contains the traced data. - */ - captureMonitoringSnapshot(resultFilePath: string, callback: (resultFilePath: string) => void): void; /** * Get a set of category groups. The category groups can change as new code paths * are reached. Once all child processes have acknowledged the getCategories - * request the callback is invoked with an array of category groups. + * request the callback is invoked with an array of category groups. Deprecated + * Soon */ getCategories(callback: (categories: string[]) => void): void; + /** + * Get a set of category groups. The category groups can change as new code paths + * are reached. + */ + getCategories(): Promise; /** * Get the maximum usage across processes of trace buffer as a percentage of the * full state. When the TraceBufferUsage value is determined the callback is - * called. + * called. Deprecated Soon */ - getTraceBufferUsage(callback: (value: number, percentage: number) => void): void; + getTraceBufferUsage(callback: (value: number) => void): void; /** - * Start monitoring on all processes. Monitoring begins immediately locally and - * asynchronously on child processes as soon as they receive the startMonitoring - * request. Once all child processes have acknowledged the startMonitoring request - * the callback will be called. + * Get the maximum usage across processes of trace buffer as a percentage of the + * full state. */ - startMonitoring(options: StartMonitoringOptions, callback: Function): void; + getTraceBufferUsage(): Promise; /** * Start recording on all processes. Recording begins immediately locally and * asynchronously on child processes as soon as they receive the EnableRecording * request. The callback will be called once all child processes have acknowledged - * the startRecording request. + * the startRecording request. Deprecated Soon */ startRecording(options: (TraceCategoriesAndOptions) | (TraceConfig), callback: Function): void; /** - * Stop monitoring on all processes. Once all child processes have acknowledged the - * stopMonitoring request the callback is called. + * Start recording on all processes. Recording begins immediately locally and + * asynchronously on child processes as soon as they receive the EnableRecording + * request. */ - stopMonitoring(callback: Function): void; + startRecording(options: (TraceCategoriesAndOptions) | (TraceConfig)): Promise; /** * Stop recording on all processes. Child processes typically cache trace data and * only rarely flush and send trace data back to the main process. This helps to @@ -2406,9 +2497,18 @@ declare namespace Electron { * acknowledged the stopRecording request, callback will be called with a file that * contains the traced data. Trace data will be written into resultFilePath if it * is not empty or into a temporary file. The actual file path will be passed to - * callback if it's not null. + * callback if it's not null. Deprecated Soon */ stopRecording(resultFilePath: string, callback: (resultFilePath: string) => void): void; + /** + * Stop recording on all processes. Child processes typically cache trace data and + * only rarely flush and send trace data back to the main process. This helps to + * minimize the runtime overhead of tracing since sending trace data over IPC can + * be an expensive operation. So, to end tracing, we must asynchronously ask all + * child processes to flush any pending trace data. Trace data will be written into + * resultFilePath if it is not empty or into a temporary file. + */ + stopRecording(resultFilePath: string): Promise; } interface Cookie { @@ -2520,20 +2620,37 @@ declare namespace Electron { /** * Writes any unwritten cookies data to disk. */ + flushStore(): Promise; + /** + * Writes any unwritten cookies data to disk. Deprecated Soon + */ flushStore(callback: Function): void; + /** + * Sends a request to get all cookies matching filter, and resolves a promise with + * the response. + */ + get(filter: Filter): Promise; /** * Sends a request to get all cookies matching filter, callback will be called with - * callback(error, cookies) on complete. + * callback(error, cookies) on complete. Deprecated Soon */ get(filter: Filter, callback: (error: Error, cookies: Cookie[]) => void): void; + /** + * Removes the cookies matching url and name + */ + remove(url: string, name: string): Promise; /** * Removes the cookies matching url and name, callback will called with callback() - * on complete. + * on complete. Deprecated Soon */ remove(url: string, name: string, callback: Function): void; + /** + * Sets a cookie with details. + */ + set(details: Details): Promise; /** * Sets a cookie with details, callback will be called with callback(error) on - * complete. + * complete. Deprecated Soon */ set(details: Details, callback: (error: Error) => void): void; } @@ -2561,15 +2678,15 @@ declare namespace Electron { id: string; } - interface CrashReporter extends EventEmitter { + interface CrashReporter { // Docs: http://electronjs.org/docs/api/crash-reporter /** * Set an extra parameter to be sent with the crash report. The values specified * here will be sent in addition to any values set via the extra option when start - * was called. This API is only available on macOS, if you need to add/update extra - * parameters on Linux and Windows after your first call to start you can call + * was called. This API is only available on macOS and windows, if you need to + * add/update extra parameters on Linux after your first call to start you can call * start again with the updated extra options. */ addExtraParameter(key: string, value: string): void; @@ -2613,13 +2730,10 @@ declare namespace Electron { * reports from them, use process.crashReporter.start instead. Pass the same * options as above along with an additional one called crashesDirectory that * should point to a directory to store the crash reports temporarily. You can test - * this out by calling process.crash() to crash the child process. Note: To collect - * crash reports from child process in Windows, you need to add this extra code as - * well. This will start the process that will monitor and send the crash reports. - * Replace submitURL, productName and crashesDirectory with appropriate values. - * Note: If you need send additional/updated extra parameters after your first call - * start you can call addExtraParameter on macOS or call start again with the - * new/updated extra parameters on Linux and Windows. Note: On macOS, Electron uses + * this out by calling process.crash() to crash the child process. Note: If you + * need send additional/updated extra parameters after your first call start you + * can call addExtraParameter on macOS or call start again with the new/updated + * extra parameters on Linux and Windows. Note: On macOS and windows, Electron uses * a new crashpad client for crash collection and reporting. If you want to enable * crash reporting, initializing crashpad from the main process using * crashReporter.start is required regardless of which process you want to collect @@ -2631,6 +2745,17 @@ declare namespace Electron { start(options: CrashReporterStartOptions): void; } + interface CustomScheme { + + // Docs: http://electronjs.org/docs/api/structures/custom-scheme + + privileges?: Privileges; + /** + * Custom schemes to be registered with options. + */ + scheme: string; + } + class Debugger extends EventEmitter { // Docs: http://electronjs.org/docs/api/debugger @@ -2712,9 +2837,13 @@ declare namespace Electron { detach(): void; isAttached(): boolean; /** - * Send given command to the debugging target. + * Send given command to the debugging target. Deprecated Soon */ sendCommand(method: string, commandParams?: any, callback?: (error: any, result: any) => void): void; + /** + * Send given command to the debugging target. + */ + sendCommand(method: string, commandParams?: any): Promise; } interface DesktopCapturer extends EventEmitter { @@ -2725,15 +2854,22 @@ declare namespace Electron { * Starts gathering information about all available desktop media sources, and * calls callback(error, sources) when finished. sources is an array of * DesktopCapturerSource objects, each DesktopCapturerSource represents a screen or - * an individual window that can be captured. + * an individual window that can be captured. Deprecated Soon */ getSources(options: SourcesOptions, callback: (error: Error, sources: DesktopCapturerSource[]) => void): void; + getSources(options: SourcesOptions): Promise; } interface DesktopCapturerSource { // Docs: http://electronjs.org/docs/api/structures/desktop-capturer-source + /** + * An icon image of the application that owns the window or null if the source has + * a type screen. The size of the icon is not known in advance and depends on what + * the the application provides. + */ + appIcon: NativeImage; /** * A unique identifier that will correspond to the id of the matching returned by * the . On some platforms, this is equivalent to the XX portion of the id field @@ -2770,7 +2906,7 @@ declare namespace Electron { * information, and gives the user the option of trusting/importing the * certificate. If you provide a browserWindow argument the dialog will be attached * to the parent window, making it modal. On Windows the options are more limited, - * due to the Win32 APIs used: + * due to the Win32 APIs used: Deprecated Soon */ showCertificateTrustDialog(browserWindow: BrowserWindow, options: CertificateTrustDialogOptions, callback: Function): void; /** @@ -2780,6 +2916,14 @@ declare namespace Electron { * to the parent window, making it modal. On Windows the options are more limited, * due to the Win32 APIs used: */ + showCertificateTrustDialog(options: CertificateTrustDialogOptions): Promise; + /** + * On macOS, this displays a modal dialog that shows a message and certificate + * information, and gives the user the option of trusting/importing the + * certificate. If you provide a browserWindow argument the dialog will be attached + * to the parent window, making it modal. On Windows the options are more limited, + * due to the Win32 APIs used: Deprecated Soon + */ showCertificateTrustDialog(options: CertificateTrustDialogOptions, callback: Function): void; /** * On macOS, this displays a modal dialog that shows a message and certificate @@ -2788,6 +2932,14 @@ declare namespace Electron { * to the parent window, making it modal. On Windows the options are more limited, * due to the Win32 APIs used: */ + showCertificateTrustDialog(browserWindow: BrowserWindow, options: CertificateTrustDialogOptions): Promise; + /** + * On macOS, this displays a modal dialog that shows a message and certificate + * information, and gives the user the option of trusting/importing the + * certificate. If you provide a browserWindow argument the dialog will be attached + * to the parent window, making it modal. On Windows the options are more limited, + * due to the Win32 APIs used: Deprecated Soon + */ showCertificateTrustDialog(browserWindow: BrowserWindow, options: CertificateTrustDialogOptions, callback: Function): void; /** * Displays a modal dialog that shows an error message. This API can be called @@ -2798,73 +2950,140 @@ declare namespace Electron { showErrorBox(title: string, content: string): void; /** * Shows a message box, it will block the process until the message box is closed. - * It returns the index of the clicked button. The browserWindow argument allows - * the dialog to attach itself to a parent window, making it modal. If a callback - * is passed, the dialog will not block the process. The API call will be - * asynchronous and the result will be passed via callback(response). + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. */ - showMessageBox(browserWindow: BrowserWindow, options: MessageBoxOptions, callback?: (response: number, checkboxChecked: boolean) => void): number; + showMessageBox(browserWindow: BrowserWindow, options: MessageBoxOptions): Promise; + /** + * Shows a message box, it will block the process until the message box is closed. + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. + */ + showMessageBox(options: MessageBoxOptions): Promise; /** * Shows a message box, it will block the process until the message box is closed. * It returns the index of the clicked button. The browserWindow argument allows - * the dialog to attach itself to a parent window, making it modal. If a callback - * is passed, the dialog will not block the process. The API call will be - * asynchronous and the result will be passed via callback(response). + * the dialog to attach itself to a parent window, making it modal. */ - showMessageBox(options: MessageBoxOptions, callback?: (response: number, checkboxChecked: boolean) => void): number; + showMessageBoxSync(browserWindow: BrowserWindow, options: MessageBoxSyncOptions): number; + /** + * Shows a message box, it will block the process until the message box is closed. + * It returns the index of the clicked button. The browserWindow argument allows + * the dialog to attach itself to a parent window, making it modal. + */ + showMessageBoxSync(options: MessageBoxSyncOptions): number; /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can * be displayed or selected when you want to limit the user to a specific type. For * example: The extensions array should contain extensions without wildcards or * dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use - * the '*' wildcard (no other wildcard is supported). If a callback is passed, the - * API call will be asynchronous and the result will be passed via - * callback(filenames). Note: On Windows and Linux an open dialog can not be both a - * file selector and a directory selector, so if you set properties to ['openFile', - * 'openDirectory'] on these platforms, a directory selector will be shown. + * the '*' wildcard (no other wildcard is supported). Note: On Windows and Linux an + * open dialog can not be both a file selector and a directory selector, so if you + * set properties to ['openFile', 'openDirectory'] on these platforms, a directory + * selector will be shown. */ - showOpenDialog(browserWindow: BrowserWindow, options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): (string[]) | (undefined); + showOpenDialog(browserWindow: BrowserWindow, options: OpenDialogOptions, callback?: Function): Promise; /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can * be displayed or selected when you want to limit the user to a specific type. For * example: The extensions array should contain extensions without wildcards or * dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use - * the '*' wildcard (no other wildcard is supported). If a callback is passed, the - * API call will be asynchronous and the result will be passed via - * callback(filenames). Note: On Windows and Linux an open dialog can not be both a - * file selector and a directory selector, so if you set properties to ['openFile', - * 'openDirectory'] on these platforms, a directory selector will be shown. + * the '*' wildcard (no other wildcard is supported). Note: On Windows and Linux an + * open dialog can not be both a file selector and a directory selector, so if you + * set properties to ['openFile', 'openDirectory'] on these platforms, a directory + * selector will be shown. */ - showOpenDialog(options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): (string[]) | (undefined); + showOpenDialog(options: OpenDialogOptions, callback?: Function): Promise; /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can - * be displayed, see dialog.showOpenDialog for an example. If a callback is passed, - * the API call will be asynchronous and the result will be passed via - * callback(filename). + * be displayed or selected when you want to limit the user to a specific type. For + * example: The extensions array should contain extensions without wildcards or + * dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use + * the '*' wildcard (no other wildcard is supported). Note: On Windows and Linux an + * open dialog can not be both a file selector and a directory selector, so if you + * set properties to ['openFile', 'openDirectory'] on these platforms, a directory + * selector will be shown. */ - showSaveDialog(browserWindow: BrowserWindow, options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): (string) | (undefined); + showOpenDialogSync(browserWindow: BrowserWindow, options: OpenDialogSyncOptions): (string[]) | (undefined); /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can - * be displayed, see dialog.showOpenDialog for an example. If a callback is passed, - * the API call will be asynchronous and the result will be passed via - * callback(filename). + * be displayed or selected when you want to limit the user to a specific type. For + * example: The extensions array should contain extensions without wildcards or + * dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use + * the '*' wildcard (no other wildcard is supported). Note: On Windows and Linux an + * open dialog can not be both a file selector and a directory selector, so if you + * set properties to ['openFile', 'openDirectory'] on these platforms, a directory + * selector will be shown. */ - showSaveDialog(options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): (string) | (undefined); + showOpenDialogSync(options: OpenDialogSyncOptions): (string[]) | (undefined); + /** + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. The filters specifies an array of file types that can + * be displayed, see dialog.showOpenDialog for an example. Note: On macOS, using + * the asynchronous version is recommended to avoid issues when expanding and + * collapsing the dialog. + */ + showSaveDialog(options: SaveDialogOptions): Promise; + /** + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. The filters specifies an array of file types that can + * be displayed, see dialog.showOpenDialog for an example. Note: On macOS, using + * the asynchronous version is recommended to avoid issues when expanding and + * collapsing the dialog. + */ + showSaveDialog(browserWindow: BrowserWindow, options: SaveDialogOptions): Promise; + /** + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. The filters specifies an array of file types that can + * be displayed, see dialog.showOpenDialog for an example. + */ + showSaveDialogSync(options: SaveDialogSyncOptions): (string) | (undefined); + /** + * The browserWindow argument allows the dialog to attach itself to a parent + * window, making it modal. The filters specifies an array of file types that can + * be displayed, see dialog.showOpenDialog for an example. + */ + showSaveDialogSync(browserWindow: BrowserWindow, options: SaveDialogSyncOptions): (string) | (undefined); } interface Display { // Docs: http://electronjs.org/docs/api/structures/display + /** + * Can be available, unavailable, unknown. + */ + accelerometerSupport: ('available' | 'unavailable' | 'unknown'); bounds: Rectangle; + /** + * The number of bits per pixel. + */ + colorDepth: number; + /** + * represent a color space (three-dimensional object which contains all realizable + * color combinations) for the purpose of color conversions + */ + colorSpace: string; + /** + * The number of bits per color component. + */ + depthPerComponent: number; /** * Unique identifier associated with the display. */ id: number; + /** + * true for an internal display and false for an external display + */ + internal: boolean; + /** + * Whether or not the display is a monochrome display. + */ + monochrome: boolean; /** * Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees. */ @@ -2951,6 +3170,7 @@ declare namespace Electron { getLastModifiedTime(): string; getMimeType(): string; getReceivedBytes(): number; + getSaveDialogOptions(): SaveDialogOptions; getSavePath(): string; getStartTime(): number; /** @@ -2977,6 +3197,12 @@ declare namespace Electron { * received bytes and restart the download from the beginning. */ resume(): void; + /** + * This API allows the user to set custom options for the save dialog that opens + * for the download item by default. The API is only available in session's + * will-download callback function. + */ + setSaveDialogOptions(options: SaveDialogOptions): void; /** * The API is only available in session's will-download callback function. If user * doesn't set the save path via the API, Electron will use the original routine to @@ -2985,6 +3211,13 @@ declare namespace Electron { setSavePath(path: string): void; } + interface Event extends GlobalEvent { + + // Docs: http://electronjs.org/docs/api/structures/event + + preventDefault: (() => void); + } + interface FileFilter { // Docs: http://electronjs.org/docs/api/structures/file-filter @@ -3012,7 +3245,17 @@ declare namespace Electron { * on macOS 10.14 Mojave unless the app has been authorized as a trusted * accessibility client: */ - register(accelerator: Accelerator, callback: Function): void; + register(accelerator: Accelerator, callback: Function): boolean; + /** + * Registers a global shortcut of all accelerator items in accelerators. The + * callback is called when any of the registered shortcuts are pressed by the user. + * When a given accelerator is already taken by other applications, this call will + * silently fail. This behavior is intended by operating systems, since they don't + * want applications to fight for global shortcuts. The following accelerators will + * not be registered successfully on macOS 10.14 Mojave unless the app has been + * authorized as a trusted accessibility client: + */ + registerAll(accelerators: string[], callback: Function): void; /** * Unregisters the global shortcut of accelerator. */ @@ -3118,15 +3361,24 @@ declare namespace Electron { */ finishTransactionByDate(date: string): void; /** - * Retrieves the product descriptions. + * Retrieves the product descriptions. Deprecated Soon */ getProducts(productIDs: string[], callback: (products: Product[]) => void): void; + /** + * Retrieves the product descriptions. + */ + getProducts(productIDs: string[]): Promise; getReceiptURL(): string; + /** + * You should listen for the transactions-updated event as soon as possible and + * certainly before you call purchaseProduct. Deprecated Soon + */ + purchaseProduct(productID: string, quantity?: number, callback?: (isProductValid: boolean) => void): void; /** * You should listen for the transactions-updated event as soon as possible and * certainly before you call purchaseProduct. */ - purchaseProduct(productID: string, quantity?: number, callback?: (isProductValid: boolean) => void): void; + purchaseProduct(productID: string, quantity?: number): Promise; } class IncomingMessage extends EventEmitter { @@ -3228,12 +3480,12 @@ declare namespace Electron { * Listens to channel, when a new message arrives listener would be called with * listener(event, args...). */ - on(channel: string, listener: Function): this; + on(channel: string, listener: (event: IpcMainEvent, ...args: any[]) => void): this; /** * Adds a one time listener function for the event. This listener is invoked only * the next time a message is sent to channel, after which it is removed. */ - once(channel: string, listener: Function): this; + once(channel: string, listener: (event: IpcMainEvent, ...args: any[]) => void): this; /** * Removes listeners of the specified channel. */ @@ -3245,6 +3497,31 @@ declare namespace Electron { removeListener(channel: string, listener: Function): this; } + interface IpcMainEvent extends Event { + + // Docs: http://electronjs.org/docs/api/structures/ipc-main-event + + /** + * The ID of the renderer frame that sent this message + */ + frameId: number; + /** + * A function that will send an IPC message to the renderer frame that sent the + * original message that you are currently handling. You should use this method to + * "reply" to the sent message in order to guaruntee the reply will go to the + * correct process and frame. + */ + reply: Function; + /** + * Set this to the value to be returned in a syncronous message + */ + returnValue: any; + /** + * Returns the webContents that sent the message + */ + sender: WebContents; + } + interface IpcRenderer extends EventEmitter { // Docs: http://electronjs.org/docs/api/ipc-renderer @@ -3253,12 +3530,12 @@ declare namespace Electron { * Listens to channel, when a new message arrives listener would be called with * listener(event, args...). */ - on(channel: string, listener: Function): this; + on(channel: string, listener: (event: IpcRendererEvent, ...args: any[]) => void): this; /** * Adds a one time listener function for the event. This listener is invoked only * the next time a message is sent to channel, after which it is removed. */ - once(channel: string, listener: Function): this; + once(channel: string, listener: (event: IpcRendererEvent, ...args: any[]) => void): this; /** * Removes all listeners, or those of the specified channel. */ @@ -3295,6 +3572,23 @@ declare namespace Electron { sendToHost(channel: string, ...args: any[]): void; } + interface IpcRendererEvent extends Event { + + // Docs: http://electronjs.org/docs/api/structures/ipc-renderer-event + + /** + * The IpcRenderer instance that emitted the event originally + */ + sender: IpcRenderer; + /** + * The webContents.id that sent the message, you can call + * event.sender.sendTo(event.senderId, ...) to reply to the message, see for more + * information. This only applies to messages sent from a different renderer. + * Messages sent directly from the main process set event.senderId to 0. + */ + senderId: number; + } + interface JumpListCategory { // Docs: http://electronjs.org/docs/api/structures/jump-list-category @@ -3358,6 +3652,37 @@ declare namespace Electron { * One of the following: */ type?: ('task' | 'separator' | 'file'); + /** + * The working directory. Default is empty. + */ + workingDirectory?: string; + } + + interface KeyboardEvent extends Event { + + // Docs: http://electronjs.org/docs/api/structures/keyboard-event + + /** + * whether an Alt key was used in an accelerator to trigger the Event + */ + altKey?: boolean; + /** + * whether the Control key was used in an accelerator to trigger the Event + */ + ctrlKey?: boolean; + /** + * whether a meta key was used in an accelerator to trigger the Event + */ + metaKey?: boolean; + /** + * whether a Shift key was used in an accelerator to trigger the Event + */ + shiftKey?: boolean; + /** + * whether an accelerator was used to trigger the event as opposed to another user + * gesture like mouse click + */ + triggeredByAccelerator?: boolean; } interface MemoryUsageDetails { @@ -3393,7 +3718,7 @@ declare namespace Electron { * usage can be referenced above. You can also attach other fields to the element * of the template and they will become properties of the constructed menu items. */ - static buildFromTemplate(template: MenuItemConstructorOptions[]): Menu; + static buildFromTemplate(template: Array<(MenuItemConstructorOptions) | (MenuItem)>): Menu; /** * Note: The returned Menu instance doesn't support dynamic addition or removal of * menu items. Instance properties can still be dynamically modified. @@ -3408,9 +3733,16 @@ declare namespace Electron { static sendActionToFirstResponder(action: string): void; /** * Sets menu as the application menu on macOS. On Windows and Linux, the menu will - * be set as each window's top menu. Passing null will remove the menu bar on - * Windows and Linux but has no effect on macOS. Note: This API has to be called - * after the ready event of app module. + * be set as each window's top menu. Also on Windows and Linux, you can use a & in + * the top-level item name to indicate which letter should get a generated + * accelerator. For example, using &File for the file menu would result in a + * generated Alt-F accelerator that opens the associated menu. The indicated + * character in the button label gets an underline. The & character is not + * displayed on the button label. Passing null will suppress the default menu. On + * Windows and Linux, this has the additional effect of removing the menu bar from + * the window. Note: The default menu will be created automatically if the app does + * not set one. It contains standard items such as File, Edit, View, Window and + * Help. */ static setApplicationMenu(menu: (Menu) | (null)): void; /** @@ -3438,10 +3770,20 @@ declare namespace Electron { // Docs: http://electronjs.org/docs/api/menu-item constructor(options: MenuItemConstructorOptions); + accelerator: string; checked: boolean; click: Function; + commandId: number; enabled: boolean; + icon: NativeImage; + id: string; label: string; + menu: Menu; + registerAccelerator: boolean; + role: string; + sublabel: string; + submenu: Menu; + type: string; visible: boolean; } @@ -3468,7 +3810,13 @@ declare namespace Electron { */ static createEmpty(): NativeImage; /** - * Creates a new NativeImage instance from buffer. + * Creates a new NativeImage instance from buffer that contains the raw bitmap + * pixel data returned by toBitmap(). The specific format is platform-dependent. + */ + static createFromBitmap(buffer: Buffer, options: CreateFromBitmapOptions): NativeImage; + /** + * Creates a new NativeImage instance from buffer. Tries to decode as PNG or JPEG + * first. */ static createFromBuffer(buffer: Buffer, options?: CreateFromBufferOptions): NativeImage; /** @@ -3556,9 +3904,14 @@ declare namespace Electron { startLogging(path: string): void; /** * Stops recording network events. If not called, net logging will automatically - * end when app quits. + * end when app quits. Deprecated Soon */ stopLogging(callback?: (path: string) => void): void; + /** + * Stops recording network events. If not called, net logging will automatically + * end when app quits. + */ + stopLogging(): Promise; /** * A Boolean property that indicates whether network logs are recorded. */ @@ -3737,6 +4090,15 @@ declare namespace Electron { once(event: 'unlock-screen', listener: Function): this; addListener(event: 'unlock-screen', listener: Function): this; removeListener(event: 'unlock-screen', listener: Function): this; + /** + * Calculate the system idle state. idleThreshold is the amount of time (in + * seconds) before considered idle. locked is available on supported systems only. + */ + getSystemIdleState(idleThreshold: number): ('active' | 'idle' | 'locked' | 'unknown'); + /** + * Calculate system idle time in seconds. + */ + getSystemIdleTime(): number; /** * Calculate the system idle state. idleThreshold is the amount of time (in * seconds) before considered idle. callback will be called synchronously on some @@ -3782,6 +4144,26 @@ declare namespace Electron { status: number; } + interface ProcessMemoryInfo { + + // Docs: http://electronjs.org/docs/api/structures/process-memory-info + + /** + * The amount of memory not shared by other processes, such as JS heap or HTML + * content in Kilobytes. + */ + private: number; + /** + * and The amount of memory currently pinned to actual physical RAM in Kilobytes. + */ + residentSet: number; + /** + * The amount of memory shared between processes, typically memory consumed by the + * Electron code itself in Kilobytes. + */ + shared: number; + } + interface ProcessMetric { // Docs: http://electronjs.org/docs/api/structures/process-metric @@ -3795,9 +4177,9 @@ declare namespace Electron { */ pid: number; /** - * Process type (Browser or Tab or GPU etc). + * Process type. One of the following values: */ - type: string; + type: ('Browser' | 'Tab' | 'Utility' | 'Zygote' | 'GPU' | 'Unknown'); } interface Product { @@ -3812,15 +4194,16 @@ declare namespace Electron { * A string that identifies the version of the content. */ contentVersion: string; - /** - * A Boolean value that indicates whether the App Store has downloadable content - * for this product. - */ - downloadable: boolean; /** * The locale formatted price of the product. */ formattedPrice: string; + /** + * A Boolean value that indicates whether the App Store has downloadable content + * for this product. true if at least one file has been associated with the + * product. + */ + isDownloadable: boolean; /** * A description of the product. */ @@ -3870,9 +4253,10 @@ declare namespace Electron { interceptStringProtocol(scheme: string, handler: (request: InterceptStringProtocolRequest, callback: (data?: string) => void) => void, completion?: (error: Error) => void): void; /** * The callback will be called with a boolean that indicates whether there is - * already a handler for scheme. + * already a handler for scheme. Deprecated Soon */ - isProtocolHandled(scheme: string, callback: (error: Error) => void): void; + isProtocolHandled(scheme: string, callback: (handled: boolean) => void): void; + isProtocolHandled(scheme: string): Promise; /** * Registers a protocol of scheme that will send a Buffer as a response. The usage * is the same with registerFileProtocol, except that the callback should be called @@ -3887,13 +4271,14 @@ declare namespace Electron { * scheme is successfully registered or completion(error) when failed. To handle * the request, the callback should be called with either the file's path or an * object that has a path property, e.g. callback(filePath) or callback({ path: - * filePath }). When callback is called with nothing, a number, or an object that - * has an error property, the request will fail with the error number you - * specified. For the available error numbers you can use, please see the net error - * list. By default the scheme is treated like http:, which is parsed differently - * than protocols that follow the "generic URI syntax" like file:, so you probably - * want to call protocol.registerStandardSchemes to have your scheme treated as a - * standard scheme. + * filePath }). The object may also have a headers property which gives a map of + * headers to values for the response headers, e.g. callback({ path: filePath, + * headers: {"Content-Security-Policy": "default-src 'none'"]}). When callback is + * called with nothing, a number, or an object that has an error property, the + * request will fail with the error number you specified. For the available error + * numbers you can use, please see the net error list. By default the scheme is + * treated like http:, which is parsed differently than protocols that follow the + * "generic URI syntax" like file:. */ registerFileProtocol(scheme: string, handler: (request: RegisterFileProtocolRequest, callback: (filePath?: string) => void) => void, completion?: (error: Error) => void): void; /** @@ -3905,24 +4290,31 @@ declare namespace Electron { * set session to null. For POST requests the uploadData object must be provided. */ registerHttpProtocol(scheme: string, handler: (request: RegisterHttpProtocolRequest, callback: (redirectRequest: RedirectRequest) => void) => void, completion?: (error: Error) => void): void; - registerServiceWorkerSchemes(schemes: string[]): void; /** - * A standard scheme adheres to what RFC 3986 calls generic URI syntax. For example - * http and https are standard schemes, while file is not. Registering a scheme as - * standard, will allow relative and absolute resources to be resolved correctly - * when served. Otherwise the scheme will behave like the file protocol, but - * without the ability to resolve relative URLs. For example when you load - * following page with custom protocol without registering it as standard scheme, - * the image will not be loaded because non-standard schemes can not recognize - * relative URLs: Registering a scheme as standard will allow access to files - * through the FileSystem API. Otherwise the renderer will throw a security error - * for the scheme. By default web storage apis (localStorage, sessionStorage, - * webSQL, indexedDB, cookies) are disabled for non standard schemes. So in general - * if you want to register a custom protocol to replace the http protocol, you have - * to register it as a standard scheme: Note: This method can only be used before - * the ready event of the app module gets emitted. + * Note: This method can only be used before the ready event of the app module gets + * emitted and can be called only once. Registers the scheme as standard, secure, + * bypasses content security policy for resources, allows registering ServiceWorker + * and supports fetch API. Specify a privilege with the value of true to enable the + * capability. An example of registering a privileged scheme, with bypassing + * Content Security Policy: A standard scheme adheres to what RFC 3986 calls + * generic URI syntax. For example http and https are standard schemes, while file + * is not. Registering a scheme as standard, will allow relative and absolute + * resources to be resolved correctly when served. Otherwise the scheme will behave + * like the file protocol, but without the ability to resolve relative URLs. For + * example when you load following page with custom protocol without registering it + * as standard scheme, the image will not be loaded because non-standard schemes + * can not recognize relative URLs: Registering a scheme as standard will allow + * access to files through the FileSystem API. Otherwise the renderer will throw a + * security error for the scheme. By default web storage apis (localStorage, + * sessionStorage, webSQL, indexedDB, cookies) are disabled for non standard + * schemes. So in general if you want to register a custom protocol to replace the + * http protocol, you have to register it as a standard scheme. + * protocol.registerSchemesAsPrivileged can be used to replicate the functionality + * of the previous protocol.registerStandardSchemes, webFrame.registerURLSchemeAs* + * and protocol.registerServiceWorkerSchemes functions that existed prior to + * Electron 5.0.0, for example: before (<= v4.x) after (>= v5.x) */ - registerStandardSchemes(schemes: string[], options?: RegisterStandardSchemesOptions): void; + registerSchemesAsPrivileged(customSchemes: CustomScheme[]): void; /** * Registers a protocol of scheme that will send a Readable as a response. The * usage is similar to the other register{Any}Protocol, except that the callback @@ -4203,22 +4595,33 @@ declare namespace Electron { * authentication. */ allowNTLMCredentialsForDomains(domains: string): void; + clearAuthCache(): Promise; + clearAuthCache(options: (RemovePassword) | (RemoveClientCertificate)): Promise; /** - * Clears the session’s HTTP authentication cache. + * Clears the session’s HTTP authentication cache. Deprecated Soon */ - clearAuthCache(options: (RemovePassword) | (RemoveClientCertificate), callback?: Function): void; + clearAuthCache(options: (RemovePassword) | (RemoveClientCertificate), callback: Function): void; /** * Clears the session’s HTTP cache. */ - clearCache(callback: Function): void; + clearCache(): Promise; + /** + * Clears the session’s HTTP cache. Deprecated Soon + */ + clearCache(callback: (error: number) => void): void; /** * Clears the host resolver cache. */ + clearHostResolverCache(): Promise; + /** + * Clears the host resolver cache. Deprecated Soon + */ clearHostResolverCache(callback?: Function): void; /** - * Clears the data of web storages. + * Clears the storage data for the current session. Deprecated Soon */ clearStorageData(options?: ClearStorageDataOptions, callback?: Function): void; + clearStorageData(options?: ClearStorageDataOptions): Promise; /** * Allows resuming cancelled or interrupted downloads from previous Session. The * API will generate a DownloadItem that can be accessed with the will-download @@ -4240,16 +4643,22 @@ declare namespace Electron { * Writes any unwritten DOMStorage data to disk. */ flushStorageData(): void; - getBlobData(identifier: string, callback: (result: Buffer) => void): void; /** - * Callback is invoked with the session's current cache size. + * Deprecated Soon */ - getCacheSize(callback: (size: number) => void): void; + getBlobData(identifier: string, callback: (result: Buffer) => void): void; + getBlobData(identifier: string): Promise; + getCacheSize(): Promise; + /** + * Callback is invoked with the session's current cache size. Deprecated Soon + */ + getCacheSize(callback: (size: number, error: number) => void): void; getPreloads(): string[]; getUserAgent(): string; + resolveProxy(url: string): Promise; /** * Resolves the proxy information for url. The callback will be called with - * callback(proxy) when the request is performed. + * callback(proxy) when the request is performed. Deprecated Soon */ resolveProxy(url: string, callback: (proxy: string) => void): void; /** @@ -4288,6 +4697,13 @@ declare namespace Electron { * proxyRules has to follow the rules below: For example: The proxyBypassRules is a * comma separated list of rules described below: */ + setProxy(config: Config): Promise; + /** + * Sets the proxy settings. When pacScript and proxyRules are provided together, + * the proxyRules option is ignored and pacScript configuration is applied. The + * proxyRules has to follow the rules below: For example: The proxyBypassRules is a + * comma separated list of rules described below: Deprecated Soon + */ setProxy(config: Config, callback: Function): void; /** * Overrides the userAgent and acceptLanguages for this session. The @@ -4319,7 +4735,12 @@ declare namespace Electron { * Open the given external protocol URL in the desktop's default manner. (For * example, mailto: URLs in the user's default mail agent). */ - openExternal(url: string, options?: OpenExternalOptions, callback?: (error: Error) => void): boolean; + openExternal(url: string, options?: OpenExternalOptions): Promise; + /** + * Open the given external protocol URL in the desktop's default manner. (For + * example, mailto: URLs in the user's default mail agent). Deprecated + */ + openExternalSync(url: string, options?: OpenExternalSyncOptions): boolean; /** * Open the given file in the desktop's default manner. */ @@ -4332,7 +4753,7 @@ declare namespace Electron { /** * Show the given file in a file manager. If possible, select the file. */ - showItemInFolder(fullPath: string): boolean; + showItemInFolder(fullPath: string): void; /** * Creates or updates a shortcut link at shortcutPath. */ @@ -4433,28 +4854,48 @@ declare namespace Electron { once(event: 'color-changed', listener: (event: Event) => void): this; addListener(event: 'color-changed', listener: (event: Event) => void): this; removeListener(event: 'color-changed', listener: (event: Event) => void): this; + on(event: 'high-contrast-color-scheme-changed', listener: (event: Event, + /** + * `true` if a high contrast theme is being used, `false` otherwise. + */ + highContrastColorScheme: boolean) => void): this; + once(event: 'high-contrast-color-scheme-changed', listener: (event: Event, + /** + * `true` if a high contrast theme is being used, `false` otherwise. + */ + highContrastColorScheme: boolean) => void): this; + addListener(event: 'high-contrast-color-scheme-changed', listener: (event: Event, + /** + * `true` if a high contrast theme is being used, `false` otherwise. + */ + highContrastColorScheme: boolean) => void): this; + removeListener(event: 'high-contrast-color-scheme-changed', listener: (event: Event, + /** + * `true` if a high contrast theme is being used, `false` otherwise. + */ + highContrastColorScheme: boolean) => void): this; on(event: 'inverted-color-scheme-changed', listener: (event: Event, /** - * `true` if an inverted color scheme, such as a high contrast theme, is being - * used, `false` otherwise. + * `true` if an inverted color scheme (a high contrast color scheme with light text + * and dark backgrounds) is being used, `false` otherwise. */ invertedColorScheme: boolean) => void): this; once(event: 'inverted-color-scheme-changed', listener: (event: Event, /** - * `true` if an inverted color scheme, such as a high contrast theme, is being - * used, `false` otherwise. + * `true` if an inverted color scheme (a high contrast color scheme with light text + * and dark backgrounds) is being used, `false` otherwise. */ invertedColorScheme: boolean) => void): this; addListener(event: 'inverted-color-scheme-changed', listener: (event: Event, /** - * `true` if an inverted color scheme, such as a high contrast theme, is being - * used, `false` otherwise. + * `true` if an inverted color scheme (a high contrast color scheme with light text + * and dark backgrounds) is being used, `false` otherwise. */ invertedColorScheme: boolean) => void): this; removeListener(event: 'inverted-color-scheme-changed', listener: (event: Event, /** - * `true` if an inverted color scheme, such as a high contrast theme, is being - * used, `false` otherwise. + * `true` if an inverted color scheme (a high contrast color scheme with light text + * and dark backgrounds) is being used, `false` otherwise. */ invertedColorScheme: boolean) => void): this; /** @@ -4467,15 +4908,26 @@ declare namespace Electron { * was not required until macOS 10.14 Mojave, so this method will always return * true if your system is running 10.13 High Sierra or lower. */ - askForMediaAccess(mediaType: 'microphone' | 'camera'): Promise; + askForMediaAccess(mediaType: 'microphone' | 'camera'): Promise; + /** + * NOTE: This API will return false on macOS systems older than Sierra 10.12.2. + */ + canPromptTouchID(): boolean; + /** + * This API is only available on macOS 10.14 Mojave or newer. + */ getAccentColor(): string; + /** + * Returns an object with system animation settings. + */ + getAnimationSettings(): AnimationSettings; /** * Gets the macOS appearance setting that you have declared you want for your * application, maps to NSApplication.appearance. You can use the * setAppLevelAppearance API to set this value. */ getAppLevelAppearance(): ('dark' | 'light' | 'unknown'); - getColor(color: '3d-dark-shadow' | '3d-face' | '3d-highlight' | '3d-light' | '3d-shadow' | 'active-border' | 'active-caption' | 'active-caption-gradient' | 'app-workspace' | 'button-text' | 'caption-text' | 'desktop' | 'disabled-text' | 'highlight' | 'highlight-text' | 'hotlight' | 'inactive-border' | 'inactive-caption' | 'inactive-caption-gradient' | 'inactive-caption-text' | 'info-background' | 'info-text' | 'menu' | 'menu-highlight' | 'menubar' | 'menu-text' | 'scrollbar' | 'window' | 'window-frame' | 'window-text'): string; + getColor(color: '3d-dark-shadow' | '3d-dark-shadow' | '3d-face' | '3d-highlight' | '3d-light' | '3d-shadow' | 'active-border' | 'active-caption' | 'active-caption-gradient' | 'app-workspace' | 'button-text' | 'caption-text' | 'desktop' | 'disabled-text' | 'highlight' | 'highlight-text' | 'hotlight' | 'inactive-border' | 'inactive-caption' | 'inactive-caption-gradient' | 'inactive-caption-text' | 'info-background' | 'info-text' | 'menu' | 'menu-highlight' | 'menubar' | 'menu-text' | 'scrollbar' | 'window' | 'window-frame' | 'window-text' | 'alternate-selected-control-text' | 'alternate-selected-control-text' | 'control-background' | 'control' | 'control-text' | 'disabled-control-text' | 'find-highlight' | 'grid' | 'header-text' | 'highlight' | 'keyboard-focus-indicator' | 'label' | 'link' | 'placeholder-text' | 'quaternary-label' | 'scrubber-textured-background' | 'secondary-label' | 'selected-content-background' | 'selected-control' | 'selected-control-text' | 'selected-menu-item' | 'selected-text-background' | 'selected-text' | 'separator' | 'shadow' | 'tertiary-label' | 'text-background' | 'text' | 'under-page-background' | 'unemphasized-selected-content-background' | 'unemphasized-selected-text-background' | 'unemphasized-selected-text' | 'window-background' | 'window-frame-text'): string; /** * Gets the macOS appearance setting that is currently applied to your application, * maps to NSApplication.effectiveAppearance Please note that until Electron is @@ -4492,6 +4944,12 @@ declare namespace Electron { * always return granted if your system is running 10.13 High Sierra or lower. */ getMediaAccessStatus(mediaType: string): ('not-determined' | 'granted' | 'denied' | 'restricted' | 'unknown'); + /** + * Returns one of several standard system colors that automatically adapt to + * vibrancy and changes in accessibility settings like 'Increase contrast' and + * 'Reduce transparency'. See Apple Documentation for more details. + */ + getSystemColor(color: 'blue' | 'brown' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'yellow'): void; /** * Some popular key and types are: */ @@ -4502,6 +4960,7 @@ declare namespace Electron { */ isAeroGlassEnabled(): boolean; isDarkMode(): boolean; + isHighContrastColorScheme(): boolean; isInvertedColorScheme(): boolean; isSwipeTrackingFromScrollEventsEnabled(): boolean; isTrustedAccessibilityClient(prompt: boolean): boolean; @@ -4514,12 +4973,22 @@ declare namespace Electron { * Posts event as native notifications of macOS. The userInfo is an Object that * contains the user information dictionary sent along with the notification. */ - postNotification(event: string, userInfo: any): void; + postNotification(event: string, userInfo: any, deliverImmediately?: boolean): void; /** * Posts event as native notifications of macOS. The userInfo is an Object that * contains the user information dictionary sent along with the notification. */ postWorkspaceNotification(event: string, userInfo: any): void; + /** + * This API itself will not protect your user data; rather, it is a mechanism to + * allow you to do so. Native apps will need to set Access Control Constants like + * kSecAccessControlUserPresence on the their keychain entry so that reading it + * would auto-prompt for Touch ID biometric consent. This could be done with + * node-keytar, such that one would store an encryption key with node-keytar and + * only fetch it if promptTouchID() resolves. NOTE: This API will return a rejected + * Promise on macOS systems older than Sierra 10.12.2. + */ + promptTouchID(reason: string): Promise; /** * Add the specified defaults to your application's NSUserDefaults. */ @@ -4608,6 +5077,10 @@ declare namespace Electron { * The string to be displayed in a JumpList. */ title: string; + /** + * The working directory. Default is empty. + */ + workingDirectory?: string; } interface ThumbarButton { @@ -4829,7 +5302,7 @@ declare namespace Electron { /** * Emitted when the tray icon is clicked. */ - on(event: 'click', listener: (event: Event, + on(event: 'click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -4838,7 +5311,7 @@ declare namespace Electron { * The position of the event. */ position: Point) => void): this; - once(event: 'click', listener: (event: Event, + once(event: 'click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -4847,7 +5320,7 @@ declare namespace Electron { * The position of the event. */ position: Point) => void): this; - addListener(event: 'click', listener: (event: Event, + addListener(event: 'click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -4856,7 +5329,7 @@ declare namespace Electron { * The position of the event. */ position: Point) => void): this; - removeListener(event: 'click', listener: (event: Event, + removeListener(event: 'click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -4868,22 +5341,22 @@ declare namespace Electron { /** * Emitted when the tray icon is double clicked. */ - on(event: 'double-click', listener: (event: Event, + on(event: 'double-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - once(event: 'double-click', listener: (event: Event, + once(event: 'double-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - addListener(event: 'double-click', listener: (event: Event, + addListener(event: 'double-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - removeListener(event: 'double-click', listener: (event: Event, + removeListener(event: 'double-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -4965,22 +5438,22 @@ declare namespace Electron { /** * Emitted when the mouse enters the tray icon. */ - on(event: 'mouse-enter', listener: (event: Event, + on(event: 'mouse-enter', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - once(event: 'mouse-enter', listener: (event: Event, + once(event: 'mouse-enter', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - addListener(event: 'mouse-enter', listener: (event: Event, + addListener(event: 'mouse-enter', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - removeListener(event: 'mouse-enter', listener: (event: Event, + removeListener(event: 'mouse-enter', listener: (event: KeyboardEvent, /** * The position of the event. */ @@ -4988,22 +5461,22 @@ declare namespace Electron { /** * Emitted when the mouse exits the tray icon. */ - on(event: 'mouse-leave', listener: (event: Event, + on(event: 'mouse-leave', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - once(event: 'mouse-leave', listener: (event: Event, + once(event: 'mouse-leave', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - addListener(event: 'mouse-leave', listener: (event: Event, + addListener(event: 'mouse-leave', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - removeListener(event: 'mouse-leave', listener: (event: Event, + removeListener(event: 'mouse-leave', listener: (event: KeyboardEvent, /** * The position of the event. */ @@ -5011,22 +5484,22 @@ declare namespace Electron { /** * Emitted when the mouse moves in the tray icon. */ - on(event: 'mouse-move', listener: (event: Event, + on(event: 'mouse-move', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - once(event: 'mouse-move', listener: (event: Event, + once(event: 'mouse-move', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - addListener(event: 'mouse-move', listener: (event: Event, + addListener(event: 'mouse-move', listener: (event: KeyboardEvent, /** * The position of the event. */ position: Point) => void): this; - removeListener(event: 'mouse-move', listener: (event: Event, + removeListener(event: 'mouse-move', listener: (event: KeyboardEvent, /** * The position of the event. */ @@ -5034,22 +5507,22 @@ declare namespace Electron { /** * Emitted when the tray icon is right clicked. */ - on(event: 'right-click', listener: (event: Event, + on(event: 'right-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - once(event: 'right-click', listener: (event: Event, + once(event: 'right-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - addListener(event: 'right-click', listener: (event: Event, + addListener(event: 'right-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ bounds: Rectangle) => void): this; - removeListener(event: 'right-click', listener: (event: Event, + removeListener(event: 'right-click', listener: (event: KeyboardEvent, /** * The bounds of tray icon. */ @@ -5068,6 +5541,7 @@ declare namespace Electron { */ getBounds(): Rectangle; getIgnoreDoubleClickEvents(): boolean; + getTitle(title: string): string; isDestroyed(): boolean; /** * Pops up the context menu of the tray icon. When menu is passed, the menu will be @@ -5080,9 +5554,9 @@ declare namespace Electron { */ setContextMenu(menu: (Menu) | (null)): void; /** - * Sets when the tray's icon background becomes highlighted (in blue). Note: You - * can use highlightMode with a BrowserWindow by toggling between 'never' and - * 'always' modes when the window visibility changes. + * Sets when the tray's icon background becomes highlighted (in blue). Deprecated + * Note: You can use highlightMode with a BrowserWindow by toggling between 'never' + * and 'always' modes when the window visibility changes. */ setHighlightMode(mode: 'selection' | 'always' | 'never'): void; /** @@ -5100,7 +5574,7 @@ declare namespace Electron { */ setPressedImage(image: (NativeImage) | (string)): void; /** - * Sets the title displayed aside of the tray icon in the status bar (Support ANSI + * Sets the title displayed next to the tray icon in the status bar (Support ANSI * colors). */ setTitle(title: string): void; @@ -5368,6 +5842,14 @@ declare namespace Electron { * coordinates of the custom cursor's hotspot. */ hotspot?: Point) => void): this; + /** + * Emitted when desktopCapturer.getSources() is called in the renderer process. + * Calling event.preventDefault() will make it return empty sources. + */ + on(event: 'desktop-capturer-get-sources', listener: (event: Event) => void): this; + once(event: 'desktop-capturer-get-sources', listener: (event: Event) => void): this; + addListener(event: 'desktop-capturer-get-sources', listener: (event: Event) => void): this; + removeListener(event: 'desktop-capturer-get-sources', listener: (event: Event) => void): this; /** * Emitted when webContents is destroyed. */ @@ -5716,6 +6198,13 @@ declare namespace Electron { once(event: 'dom-ready', listener: (event: Event) => void): this; addListener(event: 'dom-ready', listener: (event: Event) => void): this; removeListener(event: 'dom-ready', listener: (event: Event) => void): this; + /** + * Emitted when the window enters a full-screen state triggered by HTML API. + */ + on(event: 'enter-html-full-screen', listener: Function): this; + once(event: 'enter-html-full-screen', listener: Function): this; + addListener(event: 'enter-html-full-screen', listener: Function): this; + removeListener(event: 'enter-html-full-screen', listener: Function): this; /** * Emitted when a result is available for [webContents.findInPage] request. */ @@ -5727,6 +6216,45 @@ declare namespace Electron { result: Result) => void): this; removeListener(event: 'found-in-page', listener: (event: Event, result: Result) => void): this; + /** + * Emitted when the renderer process sends an asynchronous message via + * ipcRenderer.send(). + */ + on(event: 'ipc-message', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + once(event: 'ipc-message', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + addListener(event: 'ipc-message', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + removeListener(event: 'ipc-message', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + /** + * Emitted when the renderer process sends a synchronous message via + * ipcRenderer.sendSync(). + */ + on(event: 'ipc-message-sync', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + once(event: 'ipc-message-sync', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + addListener(event: 'ipc-message-sync', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + removeListener(event: 'ipc-message-sync', listener: (event: Event, + channel: string, + ...args: any[]) => void): this; + /** + * Emitted when the window leaves a full-screen state triggered by HTML API. + */ + on(event: 'leave-html-full-screen', listener: Function): this; + once(event: 'leave-html-full-screen', listener: Function): this; + addListener(event: 'leave-html-full-screen', listener: Function): this; + removeListener(event: 'leave-html-full-screen', listener: Function): this; /** * Emitted when webContents wants to do basic auth. The usage is the same with the * login event of app. @@ -5941,6 +6469,21 @@ declare namespace Electron { removeListener(event: 'plugin-crashed', listener: (event: Event, name: string, version: string) => void): this; + /** + * Emitted when the preload script preloadPath throws an unhandled exception error. + */ + on(event: 'preload-error', listener: (event: Event, + preloadPath: string, + error: Error) => void): this; + once(event: 'preload-error', listener: (event: Event, + preloadPath: string, + error: Error) => void): this; + addListener(event: 'preload-error', listener: (event: Event, + preloadPath: string, + error: Error) => void): this; + removeListener(event: 'preload-error', listener: (event: Event, + preloadPath: string, + error: Error) => void): this; /** * Emitted when remote.getBuiltin() is called in the renderer process. Calling * event.preventDefault() will prevent the module from being returned. Custom value @@ -6205,16 +6748,23 @@ declare namespace Electron { canGoBack(): boolean; canGoForward(): boolean; canGoToOffset(offset: number): boolean; + /** + * Captures a snapshot of the page within rect. Omitting rect will capture the + * whole visible page. + */ + capturePage(rect?: Rectangle): Promise; /** * Captures a snapshot of the page within rect. Upon completion callback will be * called with callback(image). The image is an instance of NativeImage that stores * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** * Captures a snapshot of the page within rect. Upon completion callback will be * called with callback(image). The image is an instance of NativeImage that stores * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(callback: (image: NativeImage) => void): void; /** @@ -6261,12 +6811,15 @@ declare namespace Electron { /** * Evaluates code in page. In the browser window some HTML APIs like * requestFullScreen can only be invoked by a gesture from the user. Setting - * userGesture to true will remove this limitation. If the result of the executed - * code is a promise the callback result will be the resolved value of the promise. - * We recommend that you use the returned Promise to handle code that results in a - * Promise. + * userGesture to true will remove this limitation. Deprecated Soon */ executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): Promise; + /** + * Evaluates code in page. In the browser window some HTML APIs like + * requestFullScreen can only be invoked by a gesture from the user. Setting + * userGesture to true will remove this limitation. + */ + executeJavaScript(code: string, userGesture?: boolean): Promise; /** * Starts a request to find all matches for the text in the web page. The result of * the request can be obtained by subscribing to found-in-page event. @@ -6288,16 +6841,8 @@ declare namespace Electron { getURL(): string; getUserAgent(): string; getWebRTCIPHandlingPolicy(): string; - /** - * Sends a request to get current zoom factor, the callback will be called with - * callback(zoomFactor). - */ - getZoomFactor(callback: (zoomFactor: number) => void): void; - /** - * Sends a request to get current zoom level, the callback will be called with - * callback(zoomLevel). - */ - getZoomLevel(callback: (zoomLevel: number) => void): void; + getZoomFactor(): number; + getZoomLevel(): number; /** * Makes the browser go back a web page. */ @@ -6314,11 +6859,6 @@ declare namespace Electron { * Navigates to the specified offset from the "current entry". */ goToOffset(offset: number): void; - /** - * Checks if any ServiceWorker is registered and returns a boolean as response to - * callback. - */ - hasServiceWorker(callback: (hasWorker: boolean) => void): void; /** * Injects CSS into the current web page. */ @@ -6335,6 +6875,10 @@ declare namespace Electron { * Opens the developer tools for the service worker context. */ inspectServiceWorker(): void; + /** + * Opens the developer tools for the shared worker context. + */ + inspectSharedWorker(): void; /** * Schedules a full repaint of the window this web contents is in. If offscreen * rendering is enabled invalidates the frame and generates a new one through the @@ -6358,13 +6902,13 @@ declare namespace Electron { * relative to the root of your application. For instance an app structure like * this: Would require code like this */ - loadFile(filePath: string, options?: LoadFileOptions): void; + loadFile(filePath: string, options?: LoadFileOptions): Promise; /** * Loads the url in the window. The url must contain the protocol prefix, e.g. the * http:// or file://. If the load should bypass http cache then use the pragma * header to achieve it. */ - loadURL(url: string, options?: LoadURLOptions): void; + loadURL(url: string, options?: LoadURLOptions): Promise; /** * Opens the devtools. When contents is a tag, the mode would be detach * by default, explicitly passing an empty mode can force using last used dock @@ -6387,13 +6931,18 @@ declare namespace Electron { * Use page-break-before: always; CSS style to force to print to a new page. */ print(options?: PrintOptions, callback?: (success: boolean) => void): void; + /** + * Prints window's web page as PDF with Chromium's preview printing custom + * settings. The landscape will be ignored if @page CSS at-rule is used in the web + * page. By default, an empty options will be regarded as: Use page-break-before: + * always; CSS style to force to print to a new page. An example of + * webContents.printToPDF: + */ + printToPDF(options: PrintToPDFOptions): Promise; /** * Prints window's web page as PDF with Chromium's preview printing custom * settings. The callback will be called with callback(error, data) on completion. - * The data is a Buffer that contains the generated PDF data. The landscape will be - * ignored if @page CSS at-rule is used in the web page. By default, an empty - * options will be regarded as: Use page-break-before: always; CSS style to force - * to print to a new page. An example of webContents.printToPDF: + * The data is a Buffer that contains the generated PDF data. Deprecated Soon */ printToPDF(options: PrintToPDFOptions, callback: (error: Error, data: Buffer) => void): void; /** @@ -6420,7 +6969,7 @@ declare namespace Electron { * Executes the editing command replaceMisspelling in web page. */ replaceMisspelling(text: string): void; - savePage(fullPath: string, saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML', callback: (error: Error) => void): boolean; + savePage(fullPath: string, saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML'): Promise; /** * Executes the editing command selectAll in web page. */ @@ -6441,6 +6990,16 @@ declare namespace Electron { * object also have following properties: */ sendInputEvent(event: Event): void; + /** + * Send an asynchronous message to a specific frame in a renderer process via + * channel. Arguments will be serialized as JSON internally and as such no + * functions or prototype chains will be included. The renderer process can handle + * the message by listening to channel with the ipcRenderer module. If you want to + * get the frameId of a given renderer context you should use the + * webFrame.routingId value. E.g. You can also read frameId from all incoming IPC + * messages in the main process. + */ + sendToFrame(frameId: number, channel: string, ...args: any[]): void; /** * Mute the audio on the current web page. */ @@ -6539,12 +7098,6 @@ declare namespace Electron { * Executes the editing command undo in web page. */ undo(): void; - /** - * Unregisters any ServiceWorker if present and returns a boolean as response to - * callback when the JS promise is fulfilled or false when the JS promise is - * rejected. - */ - unregisterServiceWorker(callback: (success: boolean) => void): void; /** * Executes the editing command unselect in web page. */ @@ -6574,11 +7127,22 @@ declare namespace Electron { * requestFullScreen can only be invoked by a gesture from the user. Setting * userGesture to true will remove this limitation. */ + executeJavaScript(code: string, userGesture?: boolean): Promise; + /** + * Evaluates code in page. In the browser window some HTML APIs like + * requestFullScreen can only be invoked by a gesture from the user. Setting + * userGesture to true will remove this limitation. Deprecated Soon + */ executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): Promise; /** - * Work like executeJavaScript but evaluates scripts in an isolated context. + * Works like executeJavaScript but evaluates scripts in an isolated context. + * Deprecated Soon */ - executeJavaScriptInIsolatedWorld(worldId: number, scripts: WebSource[], userGesture?: boolean, callback?: (result: any) => void): void; + executeJavaScriptInIsolatedWorld(worldId: number, scripts: WebSource[], userGesture?: boolean, callback?: (result: any) => void): Promise; + /** + * Works like executeJavaScript but evaluates scripts in an isolated context. + */ + executeJavaScriptInIsolatedWorld(worldId: number, scripts: WebSource[], userGesture?: boolean): Promise; findFrameByName(name: string): WebFrame; findFrameByRoutingId(routingId: number): WebFrame; getFrameForSelector(selector: string): WebFrame; @@ -6589,22 +7153,14 @@ declare namespace Electron { getResourceUsage(): ResourceUsage; getZoomFactor(): number; getZoomLevel(): number; + /** + * Inserts css as a style sheet in the document. + */ + insertCSS(css: string): void; /** * Inserts text to the focused element. */ insertText(text: string): void; - /** - * Resources will be loaded from this scheme regardless of the current page's - * Content Security Policy. - */ - registerURLSchemeAsBypassingCSP(scheme: string): void; - /** - * Registers the scheme as secure, bypasses content security policy for resources, - * allows registering ServiceWorker and supports fetch API. Specify an option with - * the value of false to omit it from the registration. An example of registering a - * privileged scheme, without bypassing Content Security Policy: - */ - registerURLSchemeAsPrivileged(scheme: string, options?: RegisterURLSchemeAsPrivilegedOptions): void; /** * Set the content security policy of the isolated world. */ @@ -6613,6 +7169,11 @@ declare namespace Electron { * Set the name of the isolated world. Useful in devtools. */ setIsolatedWorldHumanReadableName(worldId: number, name: string): void; + /** + * Set the security origin, content security policy and name of the isolated world. + * Note: If the csp is specified, then the securityOrigin also has to be specified. + */ + setIsolatedWorldInfo(worldId: number, info: Info): void; /** * Set the security origin of the isolated world. */ @@ -6623,10 +7184,12 @@ declare namespace Electron { setLayoutZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; /** * Sets a provider for spell checking in input fields and text areas. The provider - * must be an object that has a spellCheck method that returns whether the word - * passed is correctly spelled. An example of using node-spellchecker as provider: + * must be an object that has a spellCheck method that accepts an array of + * individual words for spellchecking. The spellCheck function runs asynchronously + * and calls the callback function with an array of misspelt words when complete. + * An example of using node-spellchecker as provider: */ - setSpellCheckProvider(language: string, autoCorrectWord: boolean, provider: Provider): void; + setSpellCheckProvider(language: string, provider: Provider): void; /** * Sets the maximum and minimum pinch-to-zoom level. */ @@ -6685,90 +7248,90 @@ declare namespace Electron { * The listener will be called with listener(details) when a server initiated * redirect is about to occur. */ - onBeforeRedirect(listener: (details: OnBeforeRedirectDetails) => void): void; + onBeforeRedirect(listener: ((details: OnBeforeRedirectDetails) => void) | (null)): void; /** * The listener will be called with listener(details) when a server initiated * redirect is about to occur. */ - onBeforeRedirect(filter: OnBeforeRedirectFilter, listener: (details: OnBeforeRedirectDetails) => void): void; + onBeforeRedirect(filter: OnBeforeRedirectFilter, listener: ((details: OnBeforeRedirectDetails) => void) | (null)): void; /** * The listener will be called with listener(details, callback) when a request is * about to occur. The uploadData is an array of UploadData objects. The callback - * has to be called with an response object. + * has to be called with an response object. Some examples of valid urls: */ - onBeforeRequest(listener: (details: OnBeforeRequestDetails, callback: (response: Response) => void) => void): void; + onBeforeRequest(listener: ((details: OnBeforeRequestDetails, callback: (response: Response) => void) => void) | (null)): void; /** * The listener will be called with listener(details, callback) when a request is * about to occur. The uploadData is an array of UploadData objects. The callback - * has to be called with an response object. + * has to be called with an response object. Some examples of valid urls: */ - onBeforeRequest(filter: OnBeforeRequestFilter, listener: (details: OnBeforeRequestDetails, callback: (response: Response) => void) => void): void; + onBeforeRequest(filter: OnBeforeRequestFilter, listener: ((details: OnBeforeRequestDetails, callback: (response: Response) => void) => void) | (null)): void; /** * The listener will be called with listener(details, callback) before sending an * HTTP request, once the request headers are available. This may occur after a TCP * connection is made to the server, but before any http data is sent. The callback * has to be called with an response object. */ - onBeforeSendHeaders(filter: OnBeforeSendHeadersFilter, listener: (details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void): void; + onBeforeSendHeaders(filter: OnBeforeSendHeadersFilter, listener: ((details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void) | (null)): void; /** * The listener will be called with listener(details, callback) before sending an * HTTP request, once the request headers are available. This may occur after a TCP * connection is made to the server, but before any http data is sent. The callback * has to be called with an response object. */ - onBeforeSendHeaders(listener: (details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void): void; + onBeforeSendHeaders(listener: ((details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void) | (null)): void; /** * The listener will be called with listener(details) when a request is completed. */ - onCompleted(filter: OnCompletedFilter, listener: (details: OnCompletedDetails) => void): void; + onCompleted(filter: OnCompletedFilter, listener: ((details: OnCompletedDetails) => void) | (null)): void; /** * The listener will be called with listener(details) when a request is completed. */ - onCompleted(listener: (details: OnCompletedDetails) => void): void; + onCompleted(listener: ((details: OnCompletedDetails) => void) | (null)): void; /** * The listener will be called with listener(details) when an error occurs. */ - onErrorOccurred(listener: (details: OnErrorOccurredDetails) => void): void; + onErrorOccurred(listener: ((details: OnErrorOccurredDetails) => void) | (null)): void; /** * The listener will be called with listener(details) when an error occurs. */ - onErrorOccurred(filter: OnErrorOccurredFilter, listener: (details: OnErrorOccurredDetails) => void): void; + onErrorOccurred(filter: OnErrorOccurredFilter, listener: ((details: OnErrorOccurredDetails) => void) | (null)): void; /** * The listener will be called with listener(details, callback) when HTTP response * headers of a request have been received. The callback has to be called with an * response object. */ - onHeadersReceived(filter: OnHeadersReceivedFilter, listener: (details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void): void; + onHeadersReceived(filter: OnHeadersReceivedFilter, listener: ((details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void) | (null)): void; /** * The listener will be called with listener(details, callback) when HTTP response * headers of a request have been received. The callback has to be called with an * response object. */ - onHeadersReceived(listener: (details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void): void; + onHeadersReceived(listener: ((details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void) | (null)): void; /** * The listener will be called with listener(details) when first byte of the * response body is received. For HTTP requests, this means that the status line * and response headers are available. */ - onResponseStarted(listener: (details: OnResponseStartedDetails) => void): void; + onResponseStarted(listener: ((details: OnResponseStartedDetails) => void) | (null)): void; /** * The listener will be called with listener(details) when first byte of the * response body is received. For HTTP requests, this means that the status line * and response headers are available. */ - onResponseStarted(filter: OnResponseStartedFilter, listener: (details: OnResponseStartedDetails) => void): void; + onResponseStarted(filter: OnResponseStartedFilter, listener: ((details: OnResponseStartedDetails) => void) | (null)): void; /** * The listener will be called with listener(details) just before a request is * going to be sent to the server, modifications of previous onBeforeSendHeaders * response are visible by the time this listener is fired. */ - onSendHeaders(filter: OnSendHeadersFilter, listener: (details: OnSendHeadersDetails) => void): void; + onSendHeaders(filter: OnSendHeadersFilter, listener: ((details: OnSendHeadersDetails) => void) | (null)): void; /** * The listener will be called with listener(details) just before a request is * going to be sent to the server, modifications of previous onBeforeSendHeaders * response are visible by the time this listener is fired. */ - onSendHeaders(listener: (details: OnSendHeadersDetails) => void): void; + onSendHeaders(listener: ((details: OnSendHeadersDetails) => void) | (null)): void; } interface WebSource { @@ -6963,15 +7526,24 @@ declare namespace Electron { canGoForward(): boolean; canGoToOffset(offset: number): boolean; /** - * Captures a snapshot of the webview's page. Same as - * webContents.capturePage([rect, ]callback). + * Captures a snapshot of the page within rect. Upon completion callback will be + * called with callback(image). The image is an instance of NativeImage that stores + * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(callback: (image: NativeImage) => void): void; /** - * Captures a snapshot of the webview's page. Same as - * webContents.capturePage([rect, ]callback). + * Captures a snapshot of the page within rect. Upon completion callback will be + * called with callback(image). The image is an instance of NativeImage that stores + * data of the snapshot. Omitting rect will capture the whole visible page. + * Deprecated Soon */ capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; + /** + * Captures a snapshot of the page within rect. Omitting rect will capture the + * whole visible page. + */ + capturePage(rect?: Rectangle): Promise; /** * Clears the navigation history. */ @@ -6996,12 +7568,18 @@ declare namespace Electron { * Initiates a download of the resource at url without navigating. */ downloadURL(url: string): void; + /** + * Evaluates code in page. If userGesture is set, it will create the user gesture + * context in the page. HTML APIs like requestFullScreen, which require user + * action, can take advantage of this option for automation. Deprecated Soon + */ + executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): Promise; /** * Evaluates code in page. If userGesture is set, it will create the user gesture * context in the page. HTML APIs like requestFullScreen, which require user * action, can take advantage of this option for automation. */ - executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): void; + executeJavaScript(code: string, userGesture?: boolean): Promise; /** * Starts a request to find all matches for the text in the web page. The result of * the request can be obtained by subscribing to found-in-page event. @@ -7015,16 +7593,9 @@ declare namespace Electron { * is disabled. */ getWebContents(): WebContents; - /** - * Sends a request to get current zoom factor, the callback will be called with - * callback(zoomFactor). - */ - getZoomFactor(callback: (zoomFactor: number) => void): void; - /** - * Sends a request to get current zoom level, the callback will be called with - * callback(zoomLevel). - */ - getZoomLevel(callback: (zoomLevel: number) => void): void; + getWebContentsId(): number; + getZoomFactor(): number; + getZoomLevel(): number; /** * Makes the guest page go back. */ @@ -7057,6 +7628,10 @@ declare namespace Electron { * Opens the DevTools for the service worker context present in the guest page. */ inspectServiceWorker(): void; + /** + * Opens the DevTools for the shared worker context present in the guest page. + */ + inspectSharedWorker(): void; isAudioMuted(): boolean; isCrashed(): boolean; isCurrentlyAudible(): boolean; @@ -7069,7 +7644,7 @@ declare namespace Electron { * Loads the url in the webview, the url must contain the protocol prefix, e.g. the * http:// or file://. */ - loadURL(url: string, options?: LoadURLOptions): void; + loadURL(url: string, options?: LoadURLOptions): Promise; /** * Opens a DevTools window for guest page. */ @@ -7088,9 +7663,13 @@ declare namespace Electron { print(options?: PrintOptions): void; /** * Prints webview's web page as PDF, Same as webContents.printToPDF(options, - * callback). + * callback). Deprecated Soon */ printToPDF(options: PrintToPDFOptions, callback: (error: Error, data: Buffer) => void): void; + /** + * Prints webview's web page as PDF, Same as webContents.printToPDF(options). + */ + printToPDF(options: PrintToPDFOptions): Promise; /** * Executes editing command redo in page. */ @@ -7180,14 +7759,6 @@ declare namespace Electron { * windows. Popups are disabled by default. */ // allowpopups?: string; ### VSCODE CHANGE (https://github.com/electron/electron/blob/master/docs/tutorial/security.md) ### - /** - * When this attribute is present the webview container will automatically resize - * within the bounds specified by the attributes minwidth, minheight, maxwidth, and - * maxheight. These constraints do not impact the webview unless autosize is - * enabled. When autosize is enabled, the webview container size cannot be less - * than the minimum values or greater than the maximum. - */ - autosize?: string; /** * A list of strings which specifies the blink features to be disabled separated by * ,. The full list of supported feature strings can be found in the @@ -7207,7 +7778,7 @@ declare namespace Electron { enableblinkfeatures?: string; /** * When this attribute is false the guest page in webview will not have access to - * the remote module. The remote module is avaiable by default. + * the remote module. The remote module is available by default. */ enableremotemodule?: string; /** @@ -7220,6 +7791,13 @@ declare namespace Electron { * system resources. Node integration is disabled by default in the guest page. */ nodeintegration?: string; + /** + * Experimental option for enabling NodeJS support in sub-frames such as iframes + * inside the webview. All your preloads will load for every iframe, you can use + * process.isMainFrame to determine if you are in the main frame or not. This + * option is disabled by default in the guest page. + */ + nodeintegrationinsubframes?: string; /** * Sets the session used by the page. If partition starts with persist:, the page * will use a persistent session available to all pages in the app with the same @@ -7281,14 +7859,23 @@ declare namespace Electron { * Copyright information. */ copyright?: string; + /** + * The app's build version number. + */ + version?: string; /** * Credit information. */ credits?: string; /** - * The app's build version number. + * The app's website. */ - version?: string; + website?: string; + /** + * Path to the app's icon. Will be shown as 64x64 pixels while retaining aspect + * ratio. + */ + iconPath?: string; } interface AddRepresentationOptions { @@ -7314,6 +7901,24 @@ declare namespace Electron { dataURL?: string; } + interface AnimationSettings { + /** + * Returns true if rich animations should be rendered. Looks at session type (e.g. + * remote desktop) and accessibility settings to give guidance for heavy + * animations. + */ + shouldRenderRichAnimation: boolean; + /** + * Determines on a per-platform basis whether scroll animations (e.g. produced by + * home/end key) should be enabled. + */ + scrollAnimationsEnabledBySystem: boolean; + /** + * Determines whether the user desires reduced motion based on platform APIs. + */ + prefersReducedMotion: boolean; + } + interface AppDetailsOptions { /** * Window's . It has to be set, otherwise the other options will have no effect. @@ -7357,6 +7962,16 @@ declare namespace Electron { * by default. */ height: boolean; + /** + * If true, the view's x position and width will grow and shrink proportionly with + * the window. false by default. + */ + horizontal: boolean; + /** + * If true, the view's y position and height will grow and shrink proportinaly with + * the window. false by default. + */ + vertical: boolean; } interface BitmapOptions { @@ -7475,7 +8090,9 @@ declare namespace Electron { */ kiosk?: boolean; /** - * Default window title. Default is "Electron". + * Default window title. Default is "Electron". If the HTML tag is defined + * in the HTML file loaded by loadURL(), this property will be + * ignored. */ title?: string; /** @@ -7520,8 +8137,8 @@ declare namespace Electron { enableLargerThanScreen?: boolean; /** * Window's background color as a hexadecimal value, like #66CD00 or #FFF or - * #80FFFFFF (alpha is supported if transparent is set to true). Default is #FFF - * (white). + * #80FFFFFF (alpha in #AARRGGBB format is supported if transparent is set to + * true). Default is #FFF (white). */ backgroundColor?: string; /** @@ -7633,15 +8250,24 @@ declare namespace Electron { interface CommandLine { /** * Append a switch (with optional value) to Chromium's command line. Note: This - * will not affect process.argv, and is mainly used by developers to control some - * low-level Chromium behaviors. + * will not affect process.argv. The intended usage of this function is to control + * Chromium's behavior. */ appendSwitch: (the_switch: string, value?: string) => void; /** * Append an argument to Chromium's command line. The argument will be quoted - * correctly. Note: This will not affect process.argv. + * correctly. Switches will precede arguments regardless of appending order. If + * you're appending an argument like --switch=value, consider using + * appendSwitch('switch', 'value') instead. Note: This will not affect + * process.argv. The intended usage of this function is to control Chromium's + * behavior. */ appendArgument: (value: string) => void; + hasSwitch: (the_switch: string) => boolean; + /** + * Note: When the switch is not present or has no value, it returns empty string. + */ + getSwitchValue: (the_switch: string) => string; } interface Config { @@ -7778,6 +8404,15 @@ declare namespace Electron { crashesDirectory?: string; } + interface CreateFromBitmapOptions { + width: number; + height: number; + /** + * Defaults to 1.0. + */ + scaleFactor?: number; + } + interface CreateFromBufferOptions { /** * Required for bitmap buffers. @@ -7831,7 +8466,7 @@ declare namespace Electron { image?: NativeImage; rtf?: string; /** - * The title of the url at text. + * The title of the URL at text. */ bookmark?: string; } @@ -7850,8 +8485,7 @@ declare namespace Electron { */ value?: string; /** - * The domain of the cookie; this will be normalized with a preceding dot so that - * it's also valid for subdomains. Empty by default if omitted. + * The domain of the cookie. Empty by default if omitted. */ domain?: string; /** @@ -7915,7 +8549,9 @@ declare namespace Electron { * When critical is passed, the dock icon will bounce until either the application * becomes active or the request is canceled. When informational is passed, the * dock icon will bounce for one second. However, the request remains active until - * either the application becomes active or the request is canceled. + * either the application becomes active or the request is canceled. Nota Bene: + * This method can only be used while the app is not focused; when the app is + * focused it will return -1. */ bounce: (type?: 'critical' | 'informational') => number; /** @@ -7935,15 +8571,13 @@ declare namespace Electron { * Hides the dock icon. */ hide: () => void; - /** - * Shows the dock icon. - */ - show: () => void; + show: () => Promise; isVisible: () => boolean; /** * Sets the application's dock menu. */ setMenu: (menu: Menu) => void; + getMenu: () => (Menu) | (null); /** * Sets the image associated with this dock icon. */ @@ -8094,6 +8728,21 @@ declare namespace Electron { password: string; } + interface Info { + /** + * Security origin for the isolated world. + */ + securityOrigin?: string; + /** + * Content Security Policy for the isolated world. + */ + csp?: string; + /** + * Name for isolated world. Useful in devtools. + */ + name?: string; + } + interface Input { /** * Either keyUp or keyDown. @@ -8288,12 +8937,18 @@ declare namespace Electron { * Will be called with click(menuItem, browserWindow, event) when the menu item is * clicked. */ - click?: (menuItem: MenuItem, browserWindow: BrowserWindow, event: Event) => void; + click?: (menuItem: MenuItem, browserWindow: BrowserWindow, event: KeyboardEvent) => void; /** - * Define the action of the menu item, when specified the click property will be - * ignored. See . + * Can be undo, redo, cut, copy, paste, pasteAndMatchStyle, delete, selectAll, + * reload, forceReload, toggleDevTools, resetZoom, zoomIn, zoomOut, + * togglefullscreen, window, minimize, close, help, about, services, hide, + * hideOthers, unhide, quit, startSpeaking, stopSpeaking, close, minimize, zoom, + * front, appMenu, fileMenu, editMenu, viewMenu, recentDocuments, toggleTabBar, + * selectNextTab, selectPreviousTab, mergeAllWindows, clearRecentDocuments, + * moveTabToNewWindow or windowMenu Define the action of the menu item, when + * specified the click property will be ignored. See . */ - role?: string; + role?: ('undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteAndMatchStyle' | 'delete' | 'selectAll' | 'reload' | 'forceReload' | 'toggleDevTools' | 'resetZoom' | 'zoomIn' | 'zoomOut' | 'togglefullscreen' | 'window' | 'minimize' | 'close' | 'help' | 'about' | 'services' | 'hide' | 'hideOthers' | 'unhide' | 'quit' | 'startSpeaking' | 'stopSpeaking' | 'close' | 'minimize' | 'zoom' | 'front' | 'appMenu' | 'fileMenu' | 'editMenu' | 'viewMenu' | 'recentDocuments' | 'toggleTabBar' | 'selectNextTab' | 'selectPreviousTab' | 'mergeAllWindows' | 'clearRecentDocuments' | 'moveTabToNewWindow' | 'windowMenu'); /** * Can be normal, separator, submenu, checkbox or radio. */ @@ -8306,6 +8961,11 @@ declare namespace Electron { * If false, the menu item will be greyed out and unclickable. */ enabled?: boolean; + /** + * default is true, and when false will prevent the accelerator from triggering the + * item if the item is not visible`. + */ + acceleratorWorksWhenHidden?: boolean; /** * If false, the menu item will be entirely hidden. */ @@ -8421,6 +9081,82 @@ declare namespace Electron { normalizeAccessKeys?: boolean; } + interface MessageBoxReturnValue { + /** + * The index of the clicked button. + */ + response: number; + /** + * The checked state of the checkbox if checkboxLabel was set. Otherwise false. + */ + checkboxChecked: boolean; + } + + interface MessageBoxSyncOptions { + /** + * Can be "none", "info", "error", "question" or "warning". On Windows, "question" + * displays the same icon as "info", unless you set an icon using the "icon" + * option. On macOS, both "warning" and "error" display the same warning icon. + */ + type?: string; + /** + * Array of texts for buttons. On Windows, an empty array will result in one button + * labeled "OK". + */ + buttons?: string[]; + /** + * Index of the button in the buttons array which will be selected by default when + * the message box opens. + */ + defaultId?: number; + /** + * Title of the message box, some platforms will not show it. + */ + title?: string; + /** + * Content of the message box. + */ + message: string; + /** + * Extra information of the message. + */ + detail?: string; + /** + * If provided, the message box will include a checkbox with the given label. The + * checkbox state can be inspected only when using callback. + */ + checkboxLabel?: string; + /** + * Initial checked state of the checkbox. false by default. + */ + checkboxChecked?: boolean; + icon?: (NativeImage) | (string); + /** + * The index of the button to be used to cancel the dialog, via the Esc key. By + * default this is assigned to the first button with "cancel" or "no" as the label. + * If no such labeled buttons exist and this option is not set, 0 will be used as + * the return value or callback response. + */ + cancelId?: number; + /** + * On Windows Electron will try to figure out which one of the buttons are common + * buttons (like "Cancel" or "Yes"), and show the others as command links in the + * dialog. This can make the dialog appear in the style of modern Windows apps. If + * you don't like this behavior, you can set noLink to true. + */ + noLink?: boolean; + /** + * Normalize the keyboard access keys across platforms. Default is false. Enabling + * this assumes & is used in the button labels for the placement of the keyboard + * shortcut access key and labels will be converted so they work correctly on each + * platform, & characters are removed on macOS, converted to _ on Linux, and left + * untouched on Windows. For example, a button label of Vie&w will be converted to + * Vie_w on Linux and View on macOS and can be selected via Alt-W on Windows and + * Linux. + */ + normalizeAccessKeys?: boolean; + } + interface NewWindowEvent extends Event { url: string; frameName: string; @@ -8488,6 +9224,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; redirectURL: string; statusCode: number; @@ -8513,6 +9250,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; uploadData: UploadData[]; } @@ -8531,6 +9269,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; requestHeaders: RequestHeaders; } @@ -8579,6 +9318,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; fromCache: boolean; /** @@ -8601,6 +9341,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; statusLine: string; statusCode: number; @@ -8634,6 +9375,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; responseHeaders: ResponseHeaders; /** @@ -8658,6 +9400,7 @@ declare namespace Electron { method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; requestHeaders: RequestHeaders; } @@ -8677,6 +9420,11 @@ declare namespace Electron { * back. In detach mode it's not. */ mode: ('right' | 'bottom' | 'undocked' | 'detach'); + /** + * Whether to bring the opened devtools window to the foreground. The default is + * true. + */ + activate?: boolean; } interface OpenDialogOptions { @@ -8703,6 +9451,48 @@ declare namespace Electron { securityScopedBookmarks?: boolean; } + interface OpenDialogReturnValue { + /** + * whether or not the dialog was canceled. + */ + canceled: boolean; + /** + * An array of file paths chosen by the user. If the dialog is cancelled this will + * be an empty array. + */ + filePaths?: string[]; + /** + * An array matching the filePaths array of base64 encoded strings which contains + * security scoped bookmark data. securityScopedBookmarks must be enabled for this + * to be populated. + */ + bookmarks?: string[]; + } + + interface OpenDialogSyncOptions { + title?: string; + defaultPath?: string; + /** + * Custom label for the confirmation button, when left empty the default label will + * be used. + */ + buttonLabel?: string; + filters?: FileFilter[]; + /** + * Contains which features the dialog should use. The following values are + * supported: + */ + properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory'>; + /** + * Message to display above input boxes. + */ + message?: string; + /** + * Create when packaged for the Mac App Store. + */ + securityScopedBookmarks?: boolean; + } + interface OpenExternalOptions { /** * true to bring the opened application to the foreground. The default is true. @@ -8714,6 +9504,17 @@ declare namespace Electron { workingDirectory?: string; } + interface OpenExternalSyncOptions { + /** + * true to bring the opened application to the foreground. The default is true. + */ + activate?: boolean; + /** + * The working directory. + */ + workingDirectory?: string; + } + interface PageFaviconUpdatedEvent extends Event { /** * Array of URLs. @@ -8874,21 +9675,31 @@ declare namespace Electron { landscape?: boolean; } - interface ProcessMemoryInfo { + interface Privileges { /** - * and The amount of memory currently pinned to actual physical RAM in Kilobytes. + * Default false. */ - residentSet: number; + standard?: boolean; /** - * The amount of memory not shared by other processes, such as JS heap or HTML - * content in Kilobytes. + * Default false. */ - private: number; + secure?: boolean; /** - * The amount of memory shared between processes, typically memory consumed by the - * Electron code itself in Kilobytes. + * Default false. */ - shared: number; + bypassCSP?: boolean; + /** + * Default false. + */ + allowServiceWorkers?: boolean; + /** + * Default false. + */ + supportFetchAPI?: boolean; + /** + * Default false. + */ + corsEnabled?: boolean; } interface ProgressBarOptions { @@ -8900,9 +9711,9 @@ declare namespace Electron { interface Provider { /** - * Returns Boolean. + * . */ - spellCheck: (text: string) => void; + spellCheck: (words: string[], callback: (misspeltWords: string[]) => void) => void; } interface ReadBookmark { @@ -8939,13 +9750,6 @@ declare namespace Electron { uploadData: UploadData[]; } - interface RegisterStandardSchemesOptions { - /** - * true to register the scheme as secure. Default false. - */ - secure?: boolean; - } - interface RegisterStreamProtocolRequest { url: string; headers: Headers; @@ -8961,29 +9765,6 @@ declare namespace Electron { uploadData: UploadData[]; } - interface RegisterURLSchemeAsPrivilegedOptions { - /** - * Default true. - */ - secure?: boolean; - /** - * Default true. - */ - bypassCSP?: boolean; - /** - * Default true. - */ - allowServiceWorkers?: boolean; - /** - * Default true. - */ - supportFetchAPI?: boolean; - /** - * Default true. - */ - corsEnabled?: boolean; - } - interface RelaunchOptions { args?: string[]; execPath?: string; @@ -9080,6 +9861,53 @@ declare namespace Electron { securityScopedBookmarks?: boolean; } + interface SaveDialogReturnValue { + /** + * whether or not the dialog was canceled. + */ + canceled: boolean; + /** + * If the dialog is canceled this will be undefined. + */ + filePath?: string; + /** + * Base64 encoded string which contains the security scoped bookmark data for the + * saved file. securityScopedBookmarks must be enabled for this to be present. + */ + bookmark?: string; + } + + interface SaveDialogSyncOptions { + title?: string; + /** + * Absolute directory path, absolute file path, or file name to use by default. + */ + defaultPath?: string; + /** + * Custom label for the confirmation button, when left empty the default label will + * be used. + */ + buttonLabel?: string; + filters?: FileFilter[]; + /** + * Message to display above text fields. + */ + message?: string; + /** + * Custom label for the text displayed in front of the filename text field. + */ + nameFieldLabel?: string; + /** + * Show the tags input box, defaults to true. + */ + showsTagField?: boolean; + /** + * Create a when packaged for the Mac App Store. If this option is enabled and the + * file doesn't already exist a blank file will be created at the chosen path. + */ + securityScopedBookmarks?: boolean; + } + interface Settings { /** * true to open the app at login, false to remove the app as a login item. Defaults @@ -9112,14 +9940,17 @@ declare namespace Electron { types: string[]; /** * The size that the media source thumbnail should be scaled to. Default is 150 x - * 150. + * 150. Set width or height to 0 when you do not need the thumbnails. This will + * save the processing time required for capturing the content of each window and + * screen. */ thumbnailSize?: Size; - } - - interface StartMonitoringOptions { - categoryFilter: string; - traceOptions: string; + /** + * Set to true to enable fetching window icons. The default value is false. When + * false the appIcon property of the sources return null. Same if a source has the + * type screen. + */ + fetchWindowIcons?: boolean; } interface SystemMemoryInfo { @@ -9487,7 +10318,7 @@ declare namespace Electron { */ devTools?: boolean; /** - * Whether node integration is enabled. Default is true. + * Whether node integration is enabled. Default is false. */ nodeIntegration?: boolean; /** @@ -9495,6 +10326,12 @@ declare namespace Electron { * this can be found in . */ nodeIntegrationInWorker?: boolean; + /** + * Experimental option for enabling Node.js support in sub-frames such as iframes + * and child windows. All your preloads will load for every iframe, you can use + * process.isMainFrame to determine if you are in the main frame or not. + */ + nodeIntegrationInSubFrames?: boolean; /** * Specifies a script that will be loaded before other scripts run in the page. * This script will always have access to node APIs no matter whether node @@ -9571,10 +10408,6 @@ declare namespace Electron { * Enables WebGL support. Default is true. */ webgl?: boolean; - /** - * Enables WebAudio support. Default is true. - */ - webaudio?: boolean; /** * Whether plugins should be enabled. Default is false. */ @@ -9642,19 +10475,17 @@ declare namespace Electron { */ contextIsolation?: boolean; /** - * Whether to use native window.open(). If set to true, the webPreferences of child - * window will always be the same with parent window, regardless of the parameters - * passed to window.open(). Defaults to false. This option is currently - * experimental. + * Whether to use native window.open(). Defaults to false. Child windows will + * always have node integration disabled unless nodeIntegrationInSubFrames is true. + * This option is currently experimental. */ nativeWindowOpen?: boolean; /** - * Whether to enable the . Defaults to the value of the nodeIntegration option. The - * preload script configured for the will have node integration enabled when it is - * executed so you should ensure remote/untrusted content is not able to create a - * tag with a possibly malicious preload script. You can use the - * will-attach-webview event on to strip away the preload script and to validate or - * alter the 's initial settings. + * Whether to enable the . Defaults to false. The preload script configured for the + * will have node integration enabled when it is executed so you should ensure + * remote/untrusted content is not able to create a tag with a possibly malicious + * preload script. You can use the will-attach-webview event on to strip away the + * preload script and to validate or alter the 's initial settings. */ webviewTag?: boolean; /** @@ -9678,6 +10509,17 @@ declare namespace Electron { * Default is false. */ navigateOnDragDrop?: boolean; + /** + * Autoplay policy to apply to content in the window, can be + * no-user-gesture-required, user-gesture-required, + * document-user-activation-required. Defaults to no-user-gesture-required. + */ + autoplayPolicy?: ('no-user-gesture-required' | 'user-gesture-required' | 'document-user-activation-required'); + /** + * Whether to prevent the window from resizing when entering HTML Fullscreen. + * Default is false. + */ + disableHtmlFullscreenWindowResize?: boolean; } interface DefaultFontFamily { @@ -9750,7 +10592,6 @@ declare namespace NodeJS { // addListener(event: 'loaded', listener: Function): this; // removeListener(event: 'loaded', listener: Function): this; // ### END VSCODE MODIFICATION ### - /** * Causes the main thread of the current process crash. */ @@ -9777,12 +10618,17 @@ declare namespace NodeJS { * private memory is more representative of the actual pre-compression memory usage * of the process on macOS. */ - getProcessMemoryInfo(): Electron.ProcessMemoryInfo; + getProcessMemoryInfo(): Promise; /** * Returns an object giving memory usage statistics about the entire system. Note * that all statistics are reported in Kilobytes. */ getSystemMemoryInfo(): Electron.SystemMemoryInfo; + /** + * Examples: Note: It returns the actual operating system version instead of kernel + * version on macOS unlike os.release(). + */ + getSystemVersion(): string; /** * Causes the main thread of the current process hang. */ @@ -9801,6 +10647,17 @@ declare namespace NodeJS { * this property is true in the main process, otherwise it is undefined. */ defaultApp?: boolean; + /** + * A Boolean that controls whether or not deprecation warnings are printed to + * stderr when formerly callback-based APIs converted to Promises are invoked using + * callbacks. Setting this to true will enable deprecation warnings. + */ + enablePromiseAPIs?: boolean; + /** + * A Boolean, true when the current renderer context is the "main" renderer frame. + * If you want the ID of the current frame you should use webFrame.routingId. + */ + isMainFrame?: boolean; /** * A Boolean. For Mac App Store build, this property is true, for other builds it * is undefined. @@ -9848,7 +10705,7 @@ declare namespace NodeJS { traceProcessWarnings?: boolean; /** * A String representing the current process's type, can be "browser" (i.e. main - * process) or "renderer". + * process), "renderer", or "worker" (i.e. web worker). */ type?: string; /** diff --git a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts index 4ec758b086b..6222be78028 100644 --- a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Menu, MenuItem, BrowserWindow, ipcMain, Event as IpcMainEvent } from 'electron'; +import { Menu, MenuItem, BrowserWindow, ipcMain, IpcMainEvent } from 'electron'; import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions } from 'vs/base/parts/contextmenu/common/contextmenu'; export function registerContextMenuListener(): void { diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index d12ed43d636..ebb99a4b34c 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, Event as IpcMainEvent, BrowserWindow } from 'electron'; +import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow } from 'electron'; import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform'; import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { OpenContext, IWindowOpenable } from 'vs/platform/windows/common/windows'; diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index f8bb5b22c9a..3a216fca8c0 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -653,7 +653,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { autoDetectHighContrast = false; } windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme(); - windowConfiguration.accessibilitySupport = app.isAccessibilitySupportEnabled(); + windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled; // Title style related windowConfiguration.maximized = this._win.isMaximized(); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index ef61a9e41b2..9e814c1b58b 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -14,7 +14,7 @@ import * as paths from 'vs/base/common/path'; import { whenDeleted, writeFileSync } from 'vs/base/node/pfs'; import { findFreePort, randomPort } from 'vs/base/node/ports'; import { resolveTerminalEncoding } from 'vs/base/node/encoding'; -import { isWindows } from 'vs/base/common/platform'; +import { isWindows, isLinux } from 'vs/base/common/platform'; import { ProfilingSession, Target } from 'v8-inspect-profiler'; import { isString } from 'vs/base/common/types'; @@ -360,6 +360,10 @@ export async function main(argv: string[]): Promise { options['stdio'] = 'ignore'; } + if (isLinux) { + addArg(argv, '--no-sandbox'); // Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox + } + const child = spawn(process.execPath, argv.slice(2), options); if (args.wait && waitMarkerFilePath) { diff --git a/src/vs/platform/dialogs/electron-main/dialogs.ts b/src/vs/platform/dialogs/electron-main/dialogs.ts index 7a38932aede..7b49ca50c2e 100644 --- a/src/vs/platform/dialogs/electron-main/dialogs.ts +++ b/src/vs/platform/dialogs/electron-main/dialogs.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, dialog, FileFilter, BrowserWindow } from 'electron'; +import { MessageBoxOptions, MessageBoxReturnValue, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, dialog, FileFilter, BrowserWindow } from 'electron'; import { Queue } from 'vs/base/common/async'; import { IStateService } from 'vs/platform/state/node/state'; import { isMacintosh } from 'vs/base/common/platform'; import { dirname } from 'vs/base/common/path'; import { normalizeNFC } from 'vs/base/common/normalization'; import { exists } from 'vs/base/node/pfs'; -import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { withNullAsUndefined } from 'vs/base/common/types'; import { localize } from 'vs/nls'; import { WORKSPACE_FILTER } from 'vs/platform/workspaces/common/workspaces'; @@ -139,13 +139,11 @@ export class DialogMainService implements IDialogMainService { showMessageBox(options: MessageBoxOptions, window?: BrowserWindow): Promise { return this.getDialogQueue(window).queue(async () => { - return new Promise(resolve => { - if (window) { - return dialog.showMessageBox(window, options, (response, checkboxChecked) => resolve({ response, checkboxChecked })); - } + if (window) { + return dialog.showMessageBox(window, options); + } - return dialog.showMessageBox(options); - }); + return dialog.showMessageBox(options); }); } @@ -160,17 +158,16 @@ export class DialogMainService implements IDialogMainService { } return this.getDialogQueue(window).queue(async () => { - return new Promise(resolve => { - if (window) { - dialog.showSaveDialog(window, options, filePath => resolve({ filePath })); - } else { - dialog.showSaveDialog(options, filePath => resolve({ filePath })); - } - }).then(result => { - result.filePath = normalizePath(result.filePath); + let result: SaveDialogReturnValue; + if (window) { + result = await dialog.showSaveDialog(window, options); + } else { + result = await dialog.showSaveDialog(options); + } - return result; - }); + result.filePath = normalizePath(result.filePath); + + return result; }); } @@ -195,17 +192,16 @@ export class DialogMainService implements IDialogMainService { } // Show dialog - return new Promise(resolve => { - if (window) { - dialog.showOpenDialog(window, options, filePaths => resolve({ filePaths })); - } else { - dialog.showOpenDialog(options, filePaths => resolve({ filePaths })); - } - }).then(result => { - result.filePaths = normalizePaths(result.filePaths); + let result: OpenDialogReturnValue; + if (window) { + result = await dialog.showOpenDialog(window, options); + } else { + result = await dialog.showOpenDialog(options); + } - return result; - }); + result.filePaths = normalizePaths(result.filePaths); + + return result; }); } } diff --git a/src/vs/platform/dialogs/node/dialogs.ts b/src/vs/platform/dialogs/node/dialogs.ts index aa9df3c6d94..754693da712 100644 --- a/src/vs/platform/dialogs/node/dialogs.ts +++ b/src/vs/platform/dialogs/node/dialogs.ts @@ -13,16 +13,3 @@ export interface INativeOpenDialogOptions { telemetryEventName?: string; telemetryExtraData?: ITelemetryData; } - -export interface MessageBoxReturnValue { - response: number; - checkboxChecked: boolean; -} - -export interface SaveDialogReturnValue { - filePath?: string; -} - -export interface OpenDialogReturnValue { - filePaths?: string[]; -} diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index eedee4a9f99..a0a3d5c4717 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -5,11 +5,11 @@ import { Event } from 'vs/base/common/event'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; -import { MessageBoxOptions, shell, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; +import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; import { INativeOpenWindowOptions } from 'vs/platform/windows/node/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IOpenedWindow, OpenContext, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { IElectronService } from 'vs/platform/electron/node/electron'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/node/electron.ts index ea86e1d0a26..3e9bcfee08f 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/node/electron.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { MessageBoxOptions, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, CrashReporterStartOptions } from 'electron'; +import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWindowOpenable, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { ParsedArgs } from 'vscode-minimist'; import { IProcessEnvironment } from 'vs/base/common/platform'; diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index e41d966ea84..975cb234e2e 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import * as objects from 'vs/base/common/objects'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue'; -import { BrowserWindow, ipcMain, screen, Event as IpcMainEvent, Display, shell } from 'electron'; +import { BrowserWindow, ipcMain, screen, IpcMainEvent, Display, shell } from 'electron'; import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { PerformanceInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService'; diff --git a/src/vs/platform/launch/electron-main/launchMainService.ts b/src/vs/platform/launch/electron-main/launchMainService.ts index 2e16afa9a53..8fb2fa26bc1 100644 --- a/src/vs/platform/launch/electron-main/launchMainService.ts +++ b/src/vs/platform/launch/electron-main/launchMainService.ts @@ -219,7 +219,7 @@ export class LaunchMainService implements ILaunchMainService { mainPID: process.pid, mainArguments: process.argv.slice(1), windows, - screenReader: !!app.isAccessibilitySupportEnabled(), + screenReader: !!app.accessibilitySupportEnabled, gpuFeatureStatus: app.getGPUFeatureStatus() }); } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index a27b3dabca0..53d102a2eca 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { isMacintosh, language } from 'vs/base/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { app, shell, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, Event as KeyboardEvent } from 'electron'; +import { app, shell, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, KeyboardEvent } from 'electron'; import { OpenContext, IRunActionInWindowRequest, getTitleBarStyle, IRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -361,7 +361,7 @@ export class Menubar { const servicesMenu = new Menu(); const services = new MenuItem({ label: nls.localize('mServices', "Services"), role: 'services', submenu: servicesMenu }); const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", product.nameLong), role: 'hide', accelerator: 'Command+H' }); - const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideothers', accelerator: 'Command+Alt+H' }); + const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideOthers', accelerator: 'Command+Alt+H' }); const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' }); const quit = new MenuItem(this.likeAction('workbench.action.quit', { label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => { diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 003ab9fe360..7059fa92238 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -636,7 +636,7 @@ export class SaveExtensionHostProfileAction extends Action { }] }); - if (!picked || !picked.filePath) { + if (!picked || !picked.filePath || picked.canceled) { return; } diff --git a/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js b/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js index 6992535ea97..8be7c9520a6 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js +++ b/src/vs/workbench/contrib/webview/electron-browser/pre/electron-index.js @@ -13,15 +13,6 @@ return; } hasRegistered = true; - - // @ts-ignore - require('electron').webFrame.registerURLSchemeAsPrivileged('vscode-resource', { - secure: true, - bypassCSP: false, - allowServiceWorkers: false, - supportFetchAPI: true, - corsEnabled: true - }); }; }()); diff --git a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts index a3df05aa176..a4873580a8d 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts @@ -110,7 +110,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil return this.pickFileToSaveSimplified(schema, options); } else { const result = await this.electronService.showSaveDialog(this.toNativeSaveDialogOptions(options)); - if (result && result.filePath) { + if (result && !result.canceled && result.filePath) { return URI.file(result.filePath); } } @@ -134,7 +134,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil } const result = await this.electronService.showSaveDialog(this.toNativeSaveDialogOptions(options)); - if (result && result.filePath) { + if (result && !result.canceled && result.filePath) { return URI.file(result.filePath); } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 803ae1b59af..2a50ef134f9 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -87,7 +87,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import product from 'vs/platform/product/common/product'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IElectronService } from 'vs/platform/electron/node/electron'; -import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { IBackupMainService, IWorkspaceBackupInfo } from 'vs/platform/backup/electron-main/backup'; import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; @@ -1347,9 +1347,9 @@ export class TestElectronService implements IElectronService { async minimizeWindow(): Promise { } async isWindowFocused(): Promise { return true; } async focusWindow(options?: { windowId?: number | undefined; } | undefined): Promise { } - async showMessageBox(options: Electron.MessageBoxOptions): Promise { throw new Error('Method not implemented.'); } - async showSaveDialog(options: Electron.SaveDialogOptions): Promise { throw new Error('Method not implemented.'); } - async showOpenDialog(options: Electron.OpenDialogOptions): Promise { throw new Error('Method not implemented.'); } + async showMessageBox(options: Electron.MessageBoxOptions): Promise { throw new Error('Method not implemented.'); } + async showSaveDialog(options: Electron.SaveDialogOptions): Promise { throw new Error('Method not implemented.'); } + async showOpenDialog(options: Electron.OpenDialogOptions): Promise { throw new Error('Method not implemented.'); } async pickFileFolderAndOpen(options: INativeOpenDialogOptions): Promise { } async pickFileAndOpen(options: INativeOpenDialogOptions): Promise { } async pickFolderAndOpen(options: INativeOpenDialogOptions): Promise { } @@ -1439,15 +1439,15 @@ export class TestDialogMainService implements IDialogMainService { throw new Error('Method not implemented.'); } - showMessageBox(options: Electron.MessageBoxOptions, window?: Electron.BrowserWindow | undefined): Promise { + showMessageBox(options: Electron.MessageBoxOptions, window?: Electron.BrowserWindow | undefined): Promise { throw new Error('Method not implemented.'); } - showSaveDialog(options: Electron.SaveDialogOptions, window?: Electron.BrowserWindow | undefined): Promise { + showSaveDialog(options: Electron.SaveDialogOptions, window?: Electron.BrowserWindow | undefined): Promise { throw new Error('Method not implemented.'); } - showOpenDialog(options: Electron.OpenDialogOptions, window?: Electron.BrowserWindow | undefined): Promise { + showOpenDialog(options: Electron.OpenDialogOptions, window?: Electron.BrowserWindow | undefined): Promise { throw new Error('Method not implemented.'); } } diff --git a/test/electron/index.js b/test/electron/index.js index f21b3615c0e..386515dc414 100644 --- a/test/electron/index.js +++ b/test/electron/index.js @@ -9,7 +9,7 @@ const { join } = require('path'); const path = require('path'); const mocha = require('mocha'); const events = require('events'); -const MochaJUnitReporter = require('mocha-junit-reporter'); +// const MochaJUnitReporter = require('mocha-junit-reporter'); const url = require('url'); const defaultReporterName = process.platform === 'win32' ? 'list' : 'spec'; @@ -133,12 +133,13 @@ app.on('ready', () => { if (argv.tfs) { new mocha.reporters.Spec(runner); - new MochaJUnitReporter(runner, { - reporterOptions: { - testsuitesTitle: `${argv.tfs} ${process.platform}`, - mochaFile: process.env.BUILD_ARTIFACTSTAGINGDIRECTORY ? path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${argv.tfs.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) : undefined - } - }); + // TODO@deepak the mocha Junit reporter seems to cause a hang when running with Electron 6 inside docker container + // new MochaJUnitReporter(runner, { + // reporterOptions: { + // testsuitesTitle: `${argv.tfs} ${process.platform}`, + // mochaFile: process.env.BUILD_ARTIFACTSTAGINGDIRECTORY ? path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${argv.tfs.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) : undefined + // } + // }); } else { const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter); let Reporter; From e78245a5d4eea22375c1cbaf553a72a3e8d79fb6 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 10 Oct 2019 22:05:18 +0200 Subject: [PATCH 387/435] fixes #82257 --- src/vs/workbench/contrib/scm/browser/media/scmViewlet.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css index 3a9e2683996..8bb02d5eaf1 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css +++ b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css @@ -106,6 +106,7 @@ height: 100%; background-repeat: no-repeat; background-position: 50% 50%; + margin-right: 8px; } .scm-viewlet .monaco-list .monaco-list-row .resource > .name > .monaco-icon-label > .actions { From 43dea5be0f63ed18f0f6253ae818b83736102653 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:10:29 -0700 Subject: [PATCH 388/435] Simplify array equals checks --- .../contrib/webview/browser/webviewEditorService.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index 0bc180e7e87..748c87aa3d6 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -6,17 +6,18 @@ import { equals } from 'vs/base/common/arrays'; import { IDisposable, toDisposable, UnownedDisposable } from 'vs/base/common/lifecycle'; import { values } from 'vs/base/common/map'; +import { isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; +import { EditorActivation } from 'vs/platform/editor/common/editor'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { GroupIdentifier } from 'vs/workbench/common/editor'; -import { IWebviewService, WebviewOptions, WebviewContentOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { RevivedWebviewEditorInput, WebviewInput } from './webviewEditorInput'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { EditorActivation } from 'vs/platform/editor/common/editor'; export const IWebviewEditorService = createDecorator('webviewEditorService'); @@ -95,8 +96,8 @@ export function areWebviewInputOptionsEqual(a: WebviewInputOptions, b: WebviewIn && a.allowScripts === b.allowScripts && a.retainContextWhenHidden === b.retainContextWhenHidden && a.tryRestoreScrollPosition === b.tryRestoreScrollPosition - && (a.localResourceRoots === b.localResourceRoots || (Array.isArray(a.localResourceRoots) && Array.isArray(b.localResourceRoots) && equals(a.localResourceRoots, b.localResourceRoots, (a, b) => a.toString() === b.toString()))) - && (a.portMapping === b.portMapping || (Array.isArray(a.portMapping) && Array.isArray(b.portMapping) && equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort))); + && equals(a.localResourceRoots, b.localResourceRoots, isEqual) + && equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort); } function canRevive(reviver: WebviewResolve, webview: WebviewInput): boolean { From 3ed36f094bcac8e1fe4245d14da0c75a5f7ce0db Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:25:25 -0700 Subject: [PATCH 389/435] Removing duplicated code --- .../webview/browser/webviewEditorService.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index 748c87aa3d6..9ef763aa6e8 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -197,19 +197,7 @@ export class WebviewEditorService implements IWebviewEditorService { const webview = this.createWebiew(id, extension, options); webview.state = state; - const webviewInput = new RevivedWebviewEditorInput(id, viewType, title, async (webview: WebviewInput): Promise => { - const didRevive = await this.tryRevive(webview); - if (didRevive) { - return Promise.resolve(undefined); - } - - // A reviver may not be registered yet. Put into pool and resolve promise when we can revive - let resolve: () => void; - const promise = new Promise(r => { resolve = r; }); - this._revivalPool.add(webview, resolve!); - return promise; - }, new UnownedDisposable(webview)); - + const webviewInput = new RevivedWebviewEditorInput(id, viewType, title, (webview: WebviewInput) => this.resolveWebview(webview), new UnownedDisposable(webview)); webviewInput.iconPath = iconPath; if (typeof group === 'number') { @@ -258,6 +246,7 @@ export class WebviewEditorService implements IWebviewEditorService { ): Promise { const didRevive = await this.tryRevive(webview); if (!didRevive) { + // A reviver may not be registered yet. Put into pool and resolve promise when we can revive let resolve: () => void; const promise = new Promise(r => { resolve = r; }); this._revivalPool.add(webview, resolve!); From 6af56c72141cdd6eda7c184e325280c9457d9497 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:34:04 -0700 Subject: [PATCH 390/435] Extract type alias --- .../browser/customEditorInputFactory.ts | 2 +- .../browser/webviewEditorInputFactory.ts | 2 +- .../webview/browser/webviewEditorService.ts | 59 ++++++++----------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index 6f038e2db50..69441774645 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -41,7 +41,7 @@ export class CustomEditoInputFactory extends WebviewEditorInputFactory { ): CustomFileEditorInput { const data = this.fromJson(serializedEditorInput); const id = data.id || generateUuid(); - const webviewInput = this.webviewService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation ? { + const webviewInput = this.webviewService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { location: data.extensionLocation, id: data.extensionId } : undefined, data.group); diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts index 288c2c9e537..c1a2ec0501e 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts @@ -54,7 +54,7 @@ export class WebviewEditorInputFactory implements IEditorInputFactory { serializedEditorInput: string ): WebviewInput { const data = this.fromJson(serializedEditorInput); - return this._webviewService.reviveWebview(data.id || generateUuid(), data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation ? { + return this._webviewService.reviveWebview(data.id || generateUuid(), data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { location: data.extensionLocation, id: data.extensionId } : undefined, data.group); diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index 9ef763aa6e8..118eff43cd1 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -26,6 +26,27 @@ export interface ICreateWebViewShowOptions { preserveFocus: boolean; } +export interface WebviewInputOptions extends WebviewOptions, WebviewContentOptions { + readonly tryRestoreScrollPosition?: boolean; + readonly retainContextWhenHidden?: boolean; + readonly enableCommandUris?: boolean; +} + +export function areWebviewInputOptionsEqual(a: WebviewInputOptions, b: WebviewInputOptions): boolean { + return a.enableCommandUris === b.enableCommandUris + && a.enableFindWidget === b.enableFindWidget + && a.allowScripts === b.allowScripts + && a.retainContextWhenHidden === b.retainContextWhenHidden + && a.tryRestoreScrollPosition === b.tryRestoreScrollPosition + && equals(a.localResourceRoots, b.localResourceRoots, isEqual) + && equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort); +} + +export interface WebviewExtensionDescription { + readonly location: URI; + readonly id: ExtensionIdentifier; +} + export interface IWebviewEditorService { _serviceBrand: undefined; @@ -35,10 +56,7 @@ export interface IWebviewEditorService { title: string, showOptions: ICreateWebViewShowOptions, options: WebviewInputOptions, - extension: undefined | { - location: URI, - id: ExtensionIdentifier - }, + extension: WebviewExtensionDescription | undefined, ): WebviewInput; reviveWebview( @@ -48,10 +66,7 @@ export interface IWebviewEditorService { iconPath: { light: URI, dark: URI } | undefined, state: any, options: WebviewInputOptions, - extension: undefined | { - readonly location: URI, - readonly id?: ExtensionIdentifier - }, + extension: WebviewExtensionDescription | undefined, group: number | undefined ): WebviewInput; @@ -84,22 +99,6 @@ export interface WebviewResolve { ): Promise; } -export interface WebviewInputOptions extends WebviewOptions, WebviewContentOptions { - readonly tryRestoreScrollPosition?: boolean; - readonly retainContextWhenHidden?: boolean; - readonly enableCommandUris?: boolean; -} - -export function areWebviewInputOptionsEqual(a: WebviewInputOptions, b: WebviewInputOptions): boolean { - return a.enableCommandUris === b.enableCommandUris - && a.enableFindWidget === b.enableFindWidget - && a.allowScripts === b.allowScripts - && a.retainContextWhenHidden === b.retainContextWhenHidden - && a.tryRestoreScrollPosition === b.tryRestoreScrollPosition - && equals(a.localResourceRoots, b.localResourceRoots, isEqual) - && equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort); -} - function canRevive(reviver: WebviewResolve, webview: WebviewInput): boolean { if (webview.isDisposed()) { return false; @@ -143,10 +142,7 @@ export class WebviewEditorService implements IWebviewEditorService { title: string, showOptions: ICreateWebViewShowOptions, options: WebviewInputOptions, - extension: undefined | { - location: URI, - id: ExtensionIdentifier - }, + extension: WebviewExtensionDescription | undefined, ): WebviewInput { const webview = this.createWebiew(id, extension, options); @@ -188,10 +184,7 @@ export class WebviewEditorService implements IWebviewEditorService { iconPath: { light: URI, dark: URI } | undefined, state: any, options: WebviewInputOptions, - extension: undefined | { - readonly location: URI, - readonly id: ExtensionIdentifier - }, + extension: WebviewExtensionDescription | undefined, group: number | undefined, ): WebviewInput { const webview = this.createWebiew(id, extension, options); @@ -254,7 +247,7 @@ export class WebviewEditorService implements IWebviewEditorService { } } - private createWebiew(id: string, extension: { location: URI; id: ExtensionIdentifier; } | undefined, options: WebviewInputOptions) { + private createWebiew(id: string, extension: WebviewExtensionDescription | undefined, options: WebviewInputOptions) { const webview = this._webviewService.createWebviewEditorOverlay(id, { enableFindWidget: options.enableFindWidget, retainContextWhenHidden: options.retainContextWhenHidden From b9e08fa6fa5c46240f7b0491d23ea2a9a96e7280 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:34:52 -0700 Subject: [PATCH 391/435] Fix name --- .../contrib/webview/browser/webviewEditorService.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index 118eff43cd1..ea4892d6935 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -77,7 +77,7 @@ export interface IWebviewEditorService { ): void; registerResolver( - reviver: WebviewResolve + resolver: WebviewResolver ): IDisposable; shouldPersist( @@ -89,7 +89,7 @@ export interface IWebviewEditorService { ): Promise; } -export interface WebviewResolve { +export interface WebviewResolver { canResolve( webview: WebviewInput, ): boolean; @@ -99,7 +99,7 @@ export interface WebviewResolve { ): Promise; } -function canRevive(reviver: WebviewResolve, webview: WebviewInput): boolean { +function canRevive(reviver: WebviewResolver, webview: WebviewInput): boolean { if (webview.isDisposed()) { return false; } @@ -113,7 +113,7 @@ class RevivalPool { this._awaitingRevival.push({ input, resolve }); } - public reviveFor(reviver: WebviewResolve) { + public reviveFor(reviver: WebviewResolver) { const toRevive = this._awaitingRevival.filter(({ input }) => canRevive(reviver, input)); this._awaitingRevival = this._awaitingRevival.filter(({ input }) => !canRevive(reviver, input)); @@ -126,7 +126,7 @@ class RevivalPool { export class WebviewEditorService implements IWebviewEditorService { _serviceBrand: undefined; - private readonly _revivers = new Set(); + private readonly _revivers = new Set(); private readonly _revivalPool = new RevivalPool(); constructor( @@ -200,7 +200,7 @@ export class WebviewEditorService implements IWebviewEditorService { } public registerResolver( - reviver: WebviewResolve + reviver: WebviewResolver ): IDisposable { this._revivers.add(reviver); this._revivalPool.reviveFor(reviver); From 12e72de9e4f8d1e6f975b508b75d37694c780e08 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:45:11 -0700 Subject: [PATCH 392/435] Reuse LazilyResolvedWebviewEditorInput for custom editors as well --- .../customEditor/browser/customEditorInput.ts | 24 ++++++------------- .../webview/browser/webviewEditorInput.ts | 17 ++++++------- .../webview/browser/webviewEditorService.ts | 6 ++--- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index bfaf0a98bcf..03b2c5cc047 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -6,25 +6,23 @@ import { memoize } from 'vs/base/common/decorators'; import { Emitter } from 'vs/base/common/event'; import { UnownedDisposable } from 'vs/base/common/lifecycle'; +import { Schemas } from 'vs/base/common/network'; import { basename } from 'vs/base/common/path'; -import { isEqual, DataUri } from 'vs/base/common/resources'; +import { DataUri, isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { WebviewContentState } from 'vs/editor/common/modes'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IEditorModel } from 'vs/platform/editor/common/editor'; import { ILabelService } from 'vs/platform/label/common/label'; import { ConfirmResult, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; +import { LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; import { promptSave } from 'vs/workbench/services/textfile/browser/textFileService'; -import { Schemas } from 'vs/base/common/network'; -export class CustomFileEditorInput extends WebviewInput { +export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput { public static typeId = 'workbench.editors.webviewEditor'; - private _hasResolved = false; private readonly _editorResource: URI; private _state = WebviewContentState.Readonly; @@ -33,11 +31,11 @@ export class CustomFileEditorInput extends WebviewInput { viewType: string, id: string, webview: UnownedDisposable, - @ILabelService private readonly labelService: ILabelService, - @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, + @IWebviewEditorService webviewEditorService: IWebviewEditorService, @IDialogService private readonly dialogService: IDialogService, + @ILabelService private readonly labelService: ILabelService, ) { - super(id, viewType, '', webview); + super(id, viewType, '', webview, webviewEditorService); this._editorResource = resource; } @@ -112,14 +110,6 @@ export class CustomFileEditorInput extends WebviewInput { } } - public async resolve(): Promise { - if (!this._hasResolved) { - this._hasResolved = true; - await this._webviewEditorService.resolveWebview(this); - } - return super.resolve(); - } - public setState(newState: WebviewContentState): void { this._state = newState; this._onDidChangeDirty.fire(); diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index 4980730a177..be153dbbc3f 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as dom from 'vs/base/browser/dom'; import { memoize } from 'vs/base/common/decorators'; +import { UnownedDisposable as Unowned } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { EditorInput, EditorModel, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { UnownedDisposable as Unowned } from 'vs/base/common/lifecycle'; +import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; const WebviewPanelResourceScheme = 'webview-panel'; @@ -141,24 +142,20 @@ export class WebviewInput extends EditorInput { } } -export class RevivedWebviewEditorInput extends WebviewInput { - private _revived: boolean = false; - +export class LazilyResolvedWebviewEditorInput extends WebviewInput { constructor( id: string, viewType: string, name: string, - private readonly reviver: (input: WebviewInput) => Promise, - webview: Unowned + webview: Unowned, + @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, ) { super(id, viewType, name, webview); } + @memoize public async resolve(): Promise { - if (!this._revived) { - this._revived = true; - await this.reviver(this); - } + await this._webviewEditorService.resolveWebview(this); return super.resolve(); } } diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts index ea4892d6935..56775e8f5e6 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts @@ -17,7 +17,7 @@ import { GroupIdentifier } from 'vs/workbench/common/editor'; import { IWebviewService, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; -import { RevivedWebviewEditorInput, WebviewInput } from './webviewEditorInput'; +import { LazilyResolvedWebviewEditorInput, WebviewInput } from './webviewEditorInput'; export const IWebviewEditorService = createDecorator('webviewEditorService'); @@ -190,7 +190,7 @@ export class WebviewEditorService implements IWebviewEditorService { const webview = this.createWebiew(id, extension, options); webview.state = state; - const webviewInput = new RevivedWebviewEditorInput(id, viewType, title, (webview: WebviewInput) => this.resolveWebview(webview), new UnownedDisposable(webview)); + const webviewInput = new LazilyResolvedWebviewEditorInput(id, viewType, title, new UnownedDisposable(webview), this); webviewInput.iconPath = iconPath; if (typeof group === 'number') { @@ -219,7 +219,7 @@ export class WebviewEditorService implements IWebviewEditorService { // Revived webviews may not have an actively registered reviver but we still want to presist them // since a reviver should exist when it is actually needed. - return webview instanceof RevivedWebviewEditorInput; + return webview instanceof LazilyResolvedWebviewEditorInput; } private async tryRevive( From 9c3d060aff84aad04f0bf86500dd8b8a50851da6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:51:50 -0700 Subject: [PATCH 393/435] Rename webviewEditorService to webviewWorkbenchService This matchs the naming of a few other services we have --- src/vs/workbench/api/browser/mainThreadWebview.ts | 14 +++++++------- .../customEditor/browser/customEditorInput.ts | 6 +++--- .../browser/customEditorInputFactory.ts | 8 ++++---- .../contrib/update/browser/releaseNotesEditor.ts | 8 ++++---- .../webview/browser/webview.contribution.ts | 4 ++-- .../contrib/webview/browser/webviewEditorInput.ts | 6 +++--- .../webview/browser/webviewEditorInputFactory.ts | 8 ++++---- .../contrib/webview/browser/webviewElement.ts | 2 +- ...EditorService.ts => webviewWorkbenchService.ts} | 8 ++++---- .../webview/electron-browser/webviewElement.ts | 2 +- src/vs/workbench/workbench.web.main.ts | 2 +- 11 files changed, 34 insertions(+), 34 deletions(-) rename src/vs/workbench/contrib/webview/browser/{webviewEditorService.ts => webviewWorkbenchService.ts} (96%) diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index 9f2da86e2bf..1c0153b7331 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -20,7 +20,7 @@ import { IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; -import { ICreateWebViewShowOptions, IWebviewEditorService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { ICreateWebViewShowOptions, WebviewInputOptions, IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -80,7 +80,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews @IExtensionService extensionService: IExtensionService, @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, @IEditorService private readonly _editorService: IEditorService, - @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, + @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, @IOpenerService private readonly _openerService: IOpenerService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @IProductService private readonly _productService: IProductService, @@ -93,7 +93,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews // This reviver's only job is to activate webview panel extensions // This should trigger the real reviver to be registered from the extension host side. - this._register(_webviewEditorService.registerResolver({ + this._register(_webviewWorkbenchService.registerResolver({ canResolve: (webview: WebviewInput) => { if (webview.getTypeId() === CustomFileEditorInput.typeId) { extensionService.activateByEvent(`onWebviewEditor:${(webview as CustomFileEditorInput).viewType}`); @@ -125,7 +125,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn); } - const webview = this._webviewEditorService.createWebview(handle, this.getInternalWebviewViewType(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), { + const webview = this._webviewWorkbenchService.createWebview(handle, this.getInternalWebviewViewType(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), { location: URI.revive(extensionLocation), id: extensionId }); @@ -186,7 +186,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews const targetGroup = this._editorGroupService.getGroup(viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn)) || this._editorGroupService.getGroup(webview.group || 0); if (targetGroup) { - this._webviewEditorService.revealWebview(webview, targetGroup, !!showOptions.preserveFocus); + this._webviewWorkbenchService.revealWebview(webview, targetGroup, !!showOptions.preserveFocus); } } @@ -201,7 +201,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews throw new Error(`Reviver for ${viewType} already registered`); } - this._revivers.set(viewType, this._webviewEditorService.registerResolver({ + this._revivers.set(viewType, this._webviewWorkbenchService.registerResolver({ canResolve: (webviewEditorInput) => { return webviewEditorInput.viewType === this.getInternalWebviewViewType(viewType); }, @@ -250,7 +250,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews throw new Error(`Provider for ${viewType} already registered`); } - this._editorProviders.set(viewType, this._webviewEditorService.registerResolver({ + this._editorProviders.set(viewType, this._webviewWorkbenchService.registerResolver({ canResolve: (webviewEditorInput) => { return webviewEditorInput.getTypeId() !== WebviewInput.typeId && webviewEditorInput.viewType === viewType; }, diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 03b2c5cc047..8099797cfd0 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -16,7 +16,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { ConfirmResult, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; -import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { promptSave } from 'vs/workbench/services/textfile/browser/textFileService'; export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput { @@ -31,11 +31,11 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput { viewType: string, id: string, webview: UnownedDisposable, - @IWebviewEditorService webviewEditorService: IWebviewEditorService, + @IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService, @IDialogService private readonly dialogService: IDialogService, @ILabelService private readonly labelService: ILabelService, ) { - super(id, viewType, '', webview, webviewEditorService); + super(id, viewType, '', webview, webviewWorkbenchService); this._editorResource = resource; } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index 69441774645..68dc237b508 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -9,7 +9,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; -import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; export class CustomEditoInputFactory extends WebviewEditorInputFactory { @@ -17,9 +17,9 @@ export class CustomEditoInputFactory extends WebviewEditorInputFactory { public constructor( @IInstantiationService private readonly _instantiationService: IInstantiationService, - @IWebviewEditorService private readonly webviewService: IWebviewEditorService, + @IWebviewWorkbenchService private readonly webviewWorkbenchService: IWebviewWorkbenchService, ) { - super(webviewService); + super(webviewWorkbenchService); } public serialize(input: CustomFileEditorInput): string | undefined { @@ -41,7 +41,7 @@ export class CustomEditoInputFactory extends WebviewEditorInputFactory { ): CustomFileEditorInput { const data = this.fromJson(serializedEditorInput); const id = data.id || generateUuid(); - const webviewInput = this.webviewService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { + const webviewInput = this.webviewWorkbenchService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { location: data.extensionLocation, id: data.extensionId } : undefined, data.group); diff --git a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts index 632e7c74330..21e80346285 100644 --- a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts +++ b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts @@ -17,7 +17,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IRequestService, asText } from 'vs/platform/request/common/request'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; import { KeybindingParser } from 'vs/base/common/keybindingParser'; @@ -43,7 +43,7 @@ export class ReleaseNotesManager { @ITelemetryService private readonly _telemetryService: ITelemetryService, @IEditorService private readonly _editorService: IEditorService, @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, - @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, + @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, @IExtensionService private readonly _extensionService: IExtensionService, @IProductService private readonly _productService: IProductService ) { @@ -71,9 +71,9 @@ export class ReleaseNotesManager { if (this._currentReleaseNotes) { this._currentReleaseNotes.setName(title); this._currentReleaseNotes.webview.html = html; - this._webviewEditorService.revealWebview(this._currentReleaseNotes, activeControl ? activeControl.group : this._editorGroupService.activeGroup, false); + this._webviewWorkbenchService.revealWebview(this._currentReleaseNotes, activeControl ? activeControl.group : this._editorGroupService.activeGroup, false); } else { - this._currentReleaseNotes = this._webviewEditorService.createWebview( + this._currentReleaseNotes = this._webviewWorkbenchService.createWebview( generateUuid(), 'releaseNotes', title, diff --git a/src/vs/workbench/contrib/webview/browser/webview.contribution.ts b/src/vs/workbench/contrib/webview/browser/webview.contribution.ts index 1c5572ec400..2189e68d81f 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.contribution.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.contribution.ts @@ -19,7 +19,7 @@ import { KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, webviewDeveloperCategor import { HideWebViewEditorFindCommand, ReloadWebviewAction, ShowWebViewEditorFindWidgetCommand, WebViewEditorFindNextCommand, WebViewEditorFindPreviousCommand } from '../browser/webviewCommands'; import { WebviewEditor } from '../browser/webviewEditor'; import { WebviewInput } from '../browser/webviewEditorInput'; -import { IWebviewEditorService, WebviewEditorService } from '../browser/webviewEditorService'; +import { IWebviewWorkbenchService, WebviewEditorService } from './webviewWorkbenchService'; (Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( WebviewEditor, @@ -31,7 +31,7 @@ Registry.as(EditorInputExtensions.EditorInputFactor WebviewEditorInputFactory.ID, WebviewEditorInputFactory); -registerSingleton(IWebviewEditorService, WebviewEditorService, true); +registerSingleton(IWebviewWorkbenchService, WebviewEditorService, true); const actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index be153dbbc3f..9ca0de141d6 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { EditorInput, EditorModel, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; const WebviewPanelResourceScheme = 'webview-panel'; @@ -148,14 +148,14 @@ export class LazilyResolvedWebviewEditorInput extends WebviewInput { viewType: string, name: string, webview: Unowned, - @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, + @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, ) { super(id, viewType, name, webview); } @memoize public async resolve(): Promise { - await this._webviewEditorService.resolveWebview(this); + await this._webviewWorkbenchService.resolveWebview(this); return super.resolve(); } } diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts index c1a2ec0501e..50150f357de 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts @@ -9,7 +9,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEditorInputFactory } from 'vs/workbench/common/editor'; import { WebviewInput } from './webviewEditorInput'; -import { IWebviewEditorService, WebviewInputOptions } from './webviewEditorService'; +import { IWebviewWorkbenchService, WebviewInputOptions } from './webviewWorkbenchService'; interface SerializedIconPath { light: string | UriComponents; @@ -33,11 +33,11 @@ export class WebviewEditorInputFactory implements IEditorInputFactory { public static readonly ID = WebviewInput.typeId; public constructor( - @IWebviewEditorService private readonly _webviewService: IWebviewEditorService + @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService ) { } public serialize(input: WebviewInput): string | undefined { - if (!this._webviewService.shouldPersist(input)) { + if (!this._webviewWorkbenchService.shouldPersist(input)) { return undefined; } @@ -54,7 +54,7 @@ export class WebviewEditorInputFactory implements IEditorInputFactory { serializedEditorInput: string ): WebviewInput { const data = this.fromJson(serializedEditorInput); - return this._webviewService.reviveWebview(data.id || generateUuid(), data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { + return this._webviewWorkbenchService.reviveWebview(data.id || generateUuid(), data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { location: data.extensionLocation, id: data.extensionId } : undefined, data.group); diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 3662830050b..b5e99945f8c 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -13,7 +13,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; -import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { loadLocalResource } from 'vs/workbench/contrib/webview/common/resourceLoader'; import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts similarity index 96% rename from src/vs/workbench/contrib/webview/browser/webviewEditorService.ts rename to src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts index 56775e8f5e6..51ca797460f 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts @@ -19,7 +19,7 @@ import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { LazilyResolvedWebviewEditorInput, WebviewInput } from './webviewEditorInput'; -export const IWebviewEditorService = createDecorator('webviewEditorService'); +export const IWebviewWorkbenchService = createDecorator('webviewEditorService'); export interface ICreateWebViewShowOptions { group: IEditorGroup | GroupIdentifier | ACTIVE_GROUP_TYPE | SIDE_GROUP_TYPE; @@ -47,7 +47,7 @@ export interface WebviewExtensionDescription { readonly id: ExtensionIdentifier; } -export interface IWebviewEditorService { +export interface IWebviewWorkbenchService { _serviceBrand: undefined; createWebview( @@ -123,7 +123,7 @@ class RevivalPool { } } -export class WebviewEditorService implements IWebviewEditorService { +export class WebviewEditorService implements IWebviewWorkbenchService { _serviceBrand: undefined; private readonly _revivers = new Set(); @@ -271,4 +271,4 @@ export class WebviewEditorService implements IWebviewEditorService { } } -registerSingleton(IWebviewEditorService, WebviewEditorService, true); +registerSingleton(IWebviewWorkbenchService, WebviewEditorService, true); diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 41940cec8e3..3e2a65b0f18 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -23,7 +23,7 @@ import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/p import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader'; import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; import { registerFileProtocol } from 'vs/workbench/contrib/webview/electron-browser/webviewProtocols'; -import { areWebviewInputOptionsEqual } from '../browser/webviewEditorService'; +import { areWebviewInputOptionsEqual } from '../browser/webviewWorkbenchService'; import { WebviewFindDelegate, WebviewFindWidget } from '../browser/webviewFindWidget'; interface IKeydownEvent { diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index fa9c9dd7a90..2dce5dc5939 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -96,7 +96,7 @@ import 'vs/workbench/contrib/debug/browser/extensionHostDebugService'; // Webview import 'vs/workbench/contrib/webview/browser/webviewService'; -import 'vs/workbench/contrib/webview/browser/webviewEditorService'; +import 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; // Terminal import 'vs/workbench/contrib/terminal/browser/terminalNativeService'; From 2793bdd296484f5183ff58156a9d90516d82f20b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 15:56:42 -0700 Subject: [PATCH 394/435] Fixing cycle --- .../customEditor/browser/customEditorInput.ts | 3 +-- .../webview/browser/webviewEditorInput.ts | 19 ------------- .../browser/webviewWorkbenchService.ts | 27 ++++++++++++++++--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 8099797cfd0..5a011b117eb 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -15,8 +15,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { ILabelService } from 'vs/platform/label/common/label'; import { ConfirmResult, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput'; -import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; +import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { promptSave } from 'vs/workbench/services/textfile/browser/textFileService'; export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput { diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index 9ca0de141d6..8fb1e90d878 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -9,7 +9,6 @@ import { URI } from 'vs/base/common/uri'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { EditorInput, EditorModel, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; const WebviewPanelResourceScheme = 'webview-panel'; @@ -141,21 +140,3 @@ export class WebviewInput extends EditorInput { this._group = group; } } - -export class LazilyResolvedWebviewEditorInput extends WebviewInput { - constructor( - id: string, - viewType: string, - name: string, - webview: Unowned, - @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, - ) { - super(id, viewType, name, webview); - } - - @memoize - public async resolve(): Promise { - await this._webviewWorkbenchService.resolveWebview(this); - return super.resolve(); - } -} diff --git a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts index 51ca797460f..8e06219c33c 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts @@ -4,20 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { equals } from 'vs/base/common/arrays'; +import { memoize } from 'vs/base/common/decorators'; import { IDisposable, toDisposable, UnownedDisposable } from 'vs/base/common/lifecycle'; import { values } from 'vs/base/common/map'; import { isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; -import { EditorActivation } from 'vs/platform/editor/common/editor'; +import { EditorActivation, IEditorModel } from 'vs/platform/editor/common/editor'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { GroupIdentifier } from 'vs/workbench/common/editor'; -import { IWebviewService, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; -import { LazilyResolvedWebviewEditorInput, WebviewInput } from './webviewEditorInput'; +import { WebviewInput } from './webviewEditorInput'; export const IWebviewWorkbenchService = createDecorator('webviewEditorService'); @@ -106,6 +107,26 @@ function canRevive(reviver: WebviewResolver, webview: WebviewInput): boolean { return reviver.canResolve(webview); } + +export class LazilyResolvedWebviewEditorInput extends WebviewInput { + constructor( + id: string, + viewType: string, + name: string, + webview: UnownedDisposable, + @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, + ) { + super(id, viewType, name, webview); + } + + @memoize + public async resolve(): Promise { + await this._webviewWorkbenchService.resolveWebview(this); + return super.resolve(); + } +} + + class RevivalPool { private _awaitingRevival: Array<{ input: WebviewInput, resolve: () => void }> = []; From bc87a615d41bd5c0842944bbfd5ade5ac7d08bc9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 17:29:28 -0700 Subject: [PATCH 395/435] Introduce Lazy for representing a value that is resolved when it first actually needed Adds a basic `Lazy` helper for representing a lazily created value. This is similar to `IdleValue`, except that it does not resolve the value on idle. `Lazy` is useful for defining UI elements that are potentially expensive to create but are not required right away. The code action code has been updated to use it for this purpose --- src/vs/base/common/lazy.ts | 66 +++++++++++++++++++ src/vs/base/test/common/lazy.test.ts | 64 ++++++++++++++++++ .../contrib/codeAction/codeActionCommands.ts | 29 ++++---- .../editor/contrib/codeAction/codeActionUi.ts | 38 ++++++----- .../contrib/codeAction/codeActionWidget.ts | 3 +- 5 files changed, 170 insertions(+), 30 deletions(-) create mode 100644 src/vs/base/common/lazy.ts create mode 100644 src/vs/base/test/common/lazy.test.ts diff --git a/src/vs/base/common/lazy.ts b/src/vs/base/common/lazy.ts new file mode 100644 index 00000000000..7080c984a83 --- /dev/null +++ b/src/vs/base/common/lazy.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * A value that is resolved synchronously when it is first needed. + */ +export interface Lazy { + /** + * True if the lazy value has been resolved. + */ + hasValue(): boolean; + + /** + * Get the wrapped value. + * + * This will force evaluation of the lazy value if it has not been resolved yet. Lazy values are only + * resolved once. `getValue` will re-throw exceptions that are hit while resolving the value + */ + getValue(): T; + + /** + * Create a new lazy value that is the result of applying `f` to the wrapped value. + * + * This does not force the evaluation of the current lazy value. + */ + map(f: (x: T) => R): Lazy; +} + +class LazyValue implements Lazy { + + private _didRun: boolean = false; + private _value?: T; + private _error: any; + + constructor( + private readonly executor: () => T, + ) { } + + hasValue() { return this._didRun; } + + getValue(): T { + if (!this._didRun) { + try { + this._value = this.executor(); + } catch (err) { + this._error = err; + } finally { + this._didRun = true; + } + } + if (this._error) { + throw this._error; + } + return this._value!; + } + + map(f: (x: T) => R): Lazy { + return new LazyValue(() => f(this.getValue())); + } +} + +export function lazy(executor: () => T) { + return new LazyValue(executor); +} diff --git a/src/vs/base/test/common/lazy.test.ts b/src/vs/base/test/common/lazy.test.ts new file mode 100644 index 00000000000..372bdca4789 --- /dev/null +++ b/src/vs/base/test/common/lazy.test.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. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { lazy } from 'vs/base/common/lazy'; + +suite('Lazy', () => { + + test('lazy values should only be resolved once', () => { + let counter = 0; + const value = lazy(() => ++counter); + + assert.strictEqual(value.hasValue(), false); + assert.strictEqual(value.getValue(), 1); + assert.strictEqual(value.hasValue(), true); + assert.strictEqual(value.getValue(), 1); // make sure we did not evaluate again + }); + + test('lazy values handle error case', () => { + let counter = 0; + const value = lazy(() => { throw ++counter; }); + + assert.strictEqual(value.hasValue(), false); + assert.throws(() => value.getValue(), 1); + assert.strictEqual(value.hasValue(), true); + assert.throws(() => value.getValue(), 1); + }); + + test('map should not cause lazy values to be re-resolved', () => { + let outer = 0; + let inner = 10; + const outerLazy = lazy(() => ++outer); + const innerLazy = outerLazy.map(x => [x, ++inner]); + + assert.strictEqual(outerLazy.hasValue(), false); + assert.strictEqual(innerLazy.hasValue(), false); + + assert.deepEqual(innerLazy.getValue(), [1, 11]); + assert.strictEqual(outerLazy.hasValue(), true); + assert.strictEqual(innerLazy.hasValue(), true); + assert.strictEqual(outerLazy.getValue(), 1); + + // make sure we did not evaluate again + assert.strictEqual(outerLazy.getValue(), 1); + assert.deepEqual(innerLazy.getValue(), [1, 11]); + }); + + test('map should should handle error values', () => { + let outer = 0; + let inner = 10; + const outerLazy = lazy(() => { throw ++outer; }); + const innerLazy = outerLazy.map(x => { throw ++inner; }); + + assert.strictEqual(outerLazy.hasValue(), false); + assert.strictEqual(innerLazy.hasValue(), false); + + assert.throws(() => innerLazy.getValue(), 1); // we should get result from outer + assert.strictEqual(outerLazy.hasValue(), true); + assert.strictEqual(innerLazy.hasValue(), true); + assert.throws(() => outerLazy.getValue(), 1); + }); +}); diff --git a/src/vs/editor/contrib/codeAction/codeActionCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts index 72af0135934..c95612a7f22 100644 --- a/src/vs/editor/contrib/codeAction/codeActionCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -5,6 +5,7 @@ import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { Lazy, lazy } from 'vs/base/common/lazy'; import { Disposable } from 'vs/base/common/lifecycle'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -47,7 +48,7 @@ export class QuickFixController extends Disposable implements IEditorContributio private readonly _editor: ICodeEditor; private readonly _model: CodeActionModel; - private readonly _ui: CodeActionUi; + private readonly _ui: Lazy; constructor( editor: ICodeEditor, @@ -64,27 +65,29 @@ export class QuickFixController extends Disposable implements IEditorContributio this._editor = editor; this._model = this._register(new CodeActionModel(this._editor, markerService, contextKeyService, progressService)); - this._register(this._model.onDidChangeState((newState) => this.update(newState))); + this._register(this._model.onDidChangeState(newState => this.update(newState))); - this._ui = this._register(new CodeActionUi(editor, QuickFixAction.Id, { - applyCodeAction: async (action, retrigger) => { - try { - await this._applyCodeAction(action); - } finally { - if (retrigger) { - this._trigger({ type: 'auto', filter: {} }); + this._ui = lazy(() => + this._register(new CodeActionUi(editor, QuickFixAction.Id, { + applyCodeAction: async (action, retrigger) => { + try { + await this._applyCodeAction(action); + } finally { + if (retrigger) { + this._trigger({ type: 'auto', filter: {} }); + } } } - } - }, contextMenuService, keybindingService)); + }, contextMenuService, keybindingService)) + ); } private update(newState: CodeActionsState.State): void { - this._ui.update(newState); + this._ui.getValue().update(newState); } public showCodeActions(actions: CodeActionSet, at: IAnchor | IPosition) { - return this._ui.showCodeActionList(actions, at); + return this._ui.getValue().showCodeActionList(actions, at); } public getId(): string { diff --git a/src/vs/editor/contrib/codeAction/codeActionUi.ts b/src/vs/editor/contrib/codeAction/codeActionUi.ts index a496f3e708f..8151f035cf0 100644 --- a/src/vs/editor/contrib/codeAction/codeActionUi.ts +++ b/src/vs/editor/contrib/codeAction/codeActionUi.ts @@ -17,11 +17,12 @@ import { CodeActionWidget } from './codeActionWidget'; import { LightBulbWidget } from './lightBulbWidget'; import { IPosition } from 'vs/editor/common/core/position'; import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; +import { Lazy, lazy } from 'vs/base/common/lazy'; export class CodeActionUi extends Disposable { - private readonly _codeActionWidget: CodeActionWidget; - private readonly _lightBulbWidget: LightBulbWidget; + private readonly _codeActionWidget: Lazy; + private readonly _lightBulbWidget: Lazy; private readonly _activeCodeActions = this._register(new MutableDisposable()); constructor( @@ -35,19 +36,26 @@ export class CodeActionUi extends Disposable { ) { super(); - this._codeActionWidget = this._register(new CodeActionWidget(this._editor, contextMenuService, { - onSelectCodeAction: async (action) => { - this.delegate.applyCodeAction(action, /* retrigger */ true); - } - })); - this._lightBulbWidget = this._register(new LightBulbWidget(this._editor, quickFixActionId, keybindingService)); + this._codeActionWidget = lazy(() => { + return this._register(new CodeActionWidget(this._editor, contextMenuService, { + onSelectCodeAction: async (action) => { + this.delegate.applyCodeAction(action, /* retrigger */ true); + } + })); + }); - this._register(this._lightBulbWidget.onClick(this._handleLightBulbSelect, this)); + this._lightBulbWidget = lazy(() => { + const widget = this._register(new LightBulbWidget(this._editor, quickFixActionId, keybindingService)); + this._register(widget.onClick(this._handleLightBulbSelect, this)); + return widget; + }); } public async update(newState: CodeActionsState.State): Promise { if (newState.type !== CodeActionsState.Type.Triggered) { - this._lightBulbWidget.hide(); + if (this._lightBulbWidget.hasValue()) { + this._lightBulbWidget.getValue().hide(); + } return; } @@ -59,7 +67,7 @@ export class CodeActionUi extends Disposable { return; } - this._lightBulbWidget.update(actions, newState.position); + this._lightBulbWidget.getValue().update(actions, newState.position); if (!actions.actions.length && newState.trigger.context) { MessageController.get(this._editor).showMessage(newState.trigger.context.notAvailableMessage, newState.trigger.context.position); @@ -83,10 +91,10 @@ export class CodeActionUi extends Disposable { } } this._activeCodeActions.value = actions; - this._codeActionWidget.show(actions, newState.position); + this._codeActionWidget.getValue().show(actions, newState.position); } else { // auto magically triggered - if (this._codeActionWidget.isVisible) { + if (this._codeActionWidget.getValue().isVisible) { // TODO: Figure out if we should update the showing menu? actions.dispose(); } else { @@ -96,10 +104,10 @@ export class CodeActionUi extends Disposable { } public async showCodeActionList(actions: CodeActionSet, at?: IAnchor | IPosition): Promise { - this._codeActionWidget.show(actions, at); + this._codeActionWidget.getValue().show(actions, at); } private _handleLightBulbSelect(e: { x: number, y: number, actions: CodeActionSet }): void { - this._codeActionWidget.show(e.actions, e); + this._codeActionWidget.getValue().show(e.actions, e); } } diff --git a/src/vs/editor/contrib/codeAction/codeActionWidget.ts b/src/vs/editor/contrib/codeAction/codeActionWidget.ts index 4f31015c81c..cb5b1eb4b2b 100644 --- a/src/vs/editor/contrib/codeAction/codeActionWidget.ts +++ b/src/vs/editor/contrib/codeAction/codeActionWidget.ts @@ -21,7 +21,7 @@ interface CodeActionWidgetDelegate { export class CodeActionWidget extends Disposable { - private _visible: boolean; + private _visible: boolean = false; private readonly _showingActions = this._register(new MutableDisposable()); constructor( @@ -30,7 +30,6 @@ export class CodeActionWidget extends Disposable { private readonly _delegate: CodeActionWidgetDelegate, ) { super(); - this._visible = false; } public async show(codeActions: CodeActionSet, at?: IAnchor | IPosition): Promise { From 3310b78eae6b058951c2fc1388b706b5e62ec193 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 17:44:31 -0700 Subject: [PATCH 396/435] Be more lazy about creating webviews --- .../customEditor/browser/customEditorInput.ts | 3 ++- .../browser/customEditorInputFactory.ts | 15 ++++++++++----- .../customEditor/browser/customEditors.ts | 7 +++++-- .../webview/browser/webviewEditorInput.ts | 14 ++++++++------ .../webview/browser/webviewWorkbenchService.ts | 17 ++++++++++------- .../webview/electron-browser/webviewElement.ts | 4 ---- 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 5a011b117eb..46ce92e8f15 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -5,6 +5,7 @@ import { memoize } from 'vs/base/common/decorators'; import { Emitter } from 'vs/base/common/event'; +import { Lazy } from 'vs/base/common/lazy'; import { UnownedDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { basename } from 'vs/base/common/path'; @@ -29,7 +30,7 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput { resource: URI, viewType: string, id: string, - webview: UnownedDisposable, + webview: Lazy>, @IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService, @IDialogService private readonly dialogService: IDialogService, @ILabelService private readonly labelService: ILabelService, diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index 68dc237b508..f98e014bd68 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -10,6 +10,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; +import { lazy } from 'vs/base/common/lazy'; export class CustomEditoInputFactory extends WebviewEditorInputFactory { @@ -41,12 +42,16 @@ export class CustomEditoInputFactory extends WebviewEditorInputFactory { ): CustomFileEditorInput { const data = this.fromJson(serializedEditorInput); const id = data.id || generateUuid(); - const webviewInput = this.webviewWorkbenchService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { - location: data.extensionLocation, - id: data.extensionId - } : undefined, data.group); - const customInput = this._instantiationService.createInstance(CustomFileEditorInput, URI.from((data as any).editorResource), data.viewType, id, new UnownedDisposable(webviewInput.webview)); + const webview = lazy(() => { + const webviewInput = this.webviewWorkbenchService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { + location: data.extensionLocation, + id: data.extensionId + } : undefined, data.group); + return new UnownedDisposable(webviewInput.webview); + }); + + const customInput = this._instantiationService.createInstance(CustomFileEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview); if (typeof data.group === 'number') { customInput.updateGroup(data.group); } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 19677c10188..1543b72018a 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -29,6 +29,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService'; import { CustomFileEditorInput } from './customEditorInput'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { lazy } from 'vs/base/common/lazy'; const defaultEditorId = 'default'; @@ -168,8 +169,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ options?: { readonly customClasses: string; }, ): CustomFileEditorInput { const id = generateUuid(); - const webview = this.webviewService.createWebviewEditorOverlay(id, { customClasses: options ? options.customClasses : undefined }, {}); - const input = this.instantiationService.createInstance(CustomFileEditorInput, resource, viewType, id, new UnownedDisposable(webview)); + const webview = lazy(() => { + return new UnownedDisposable(this.webviewService.createWebviewEditorOverlay(id, { customClasses: options ? options.customClasses : undefined }, {})); + }); + const input = this.instantiationService.createInstance(CustomFileEditorInput, resource, viewType, id, webview); if (group) { input.updateGroup(group.id); } diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index 8fb1e90d878..ef25742c11f 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -2,8 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + import * as dom from 'vs/base/browser/dom'; import { memoize } from 'vs/base/common/decorators'; +import { Lazy } from 'vs/base/common/lazy'; import { UnownedDisposable as Unowned } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IEditorModel } from 'vs/platform/editor/common/editor'; @@ -60,19 +62,19 @@ export class WebviewInput extends EditorInput { private _name: string; private _iconPath?: { light: URI, dark: URI }; private _group?: GroupIdentifier; - private readonly _webview: WebviewEditorOverlay; + private readonly _webview: Lazy; constructor( public readonly id: string, public readonly viewType: string, name: string, - webview: Unowned + webview: Lazy> ) { super(); this._name = name; - this._webview = this._register(webview.acquire()); // The input owns this webview + this._webview = webview.map(value => this._register(value.acquire())); // The input owns this webview } public getTypeId(): string { @@ -103,12 +105,12 @@ export class WebviewInput extends EditorInput { this._onDidChangeLabel.fire(); } - public get webview() { - return this._webview; + public get webview(): WebviewEditorOverlay { + return this._webview.getValue(); } public get extension() { - return this._webview.extension; + return this._webview.getValue().extension; } public get iconPath() { diff --git a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts index 8e06219c33c..5be538dcea4 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts @@ -19,6 +19,7 @@ import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewOp import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { WebviewInput } from './webviewEditorInput'; +import { Lazy, lazy } from 'vs/base/common/lazy'; export const IWebviewWorkbenchService = createDecorator('webviewEditorService'); @@ -113,7 +114,7 @@ export class LazilyResolvedWebviewEditorInput extends WebviewInput { id: string, viewType: string, name: string, - webview: UnownedDisposable, + webview: Lazy>, @IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService, ) { super(id, viewType, name, webview); @@ -165,9 +166,8 @@ export class WebviewEditorService implements IWebviewWorkbenchService { options: WebviewInputOptions, extension: WebviewExtensionDescription | undefined, ): WebviewInput { - const webview = this.createWebiew(id, extension, options); - - const webviewInput = new WebviewInput(id, viewType, title, new UnownedDisposable(webview)); + const webview = lazy(() => new UnownedDisposable(this.createWebiew(id, extension, options))); + const webviewInput = new WebviewInput(id, viewType, title, webview); this._editorService.openEditor(webviewInput, { pinned: true, preserveFocus: showOptions.preserveFocus, @@ -208,10 +208,13 @@ export class WebviewEditorService implements IWebviewWorkbenchService { extension: WebviewExtensionDescription | undefined, group: number | undefined, ): WebviewInput { - const webview = this.createWebiew(id, extension, options); - webview.state = state; + const webview = lazy(() => { + const webview = this.createWebiew(id, extension, options); + webview.state = state; + return new UnownedDisposable(webview); + }); - const webviewInput = new LazilyResolvedWebviewEditorInput(id, viewType, title, new UnownedDisposable(webview), this); + const webviewInput = new LazilyResolvedWebviewEditorInput(id, viewType, title, webview, this); webviewInput.iconPath = iconPath; if (typeof group === 'number') { diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 3e2a65b0f18..a27ea558213 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -435,10 +435,6 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, this._webview = undefined; } - if (this._webviewFindWidget) { - this._webviewFindWidget.dispose(); - this._webviewFindWidget = undefined; - } super.dispose(); } From 54c29559e5a71daef13c099af2cbba6f524f2d6e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 18:35:25 -0700 Subject: [PATCH 397/435] Remove webview.update method this function is no longer being used --- .../webview/browser/dynamicWebviewEditorOverlay.ts | 8 -------- src/vs/workbench/contrib/webview/browser/webview.ts | 5 ----- .../contrib/webview/browser/webviewElement.ts | 12 ------------ .../webview/electron-browser/webviewElement.ts | 12 ------------ 4 files changed, 37 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index b706a2d16a5..31f778e3bfc 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -176,14 +176,6 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd } } - update(html: string, options: WebviewContentOptions, retainContextWhenHidden: boolean): void { - this._contentOptions = options; - this._html = html; - this.withWebview(webview => { - webview.update(html, options, retainContextWhenHidden); - }); - } - layout(): void { this.withWebview(webview => webview.layout()); } focus(): void { this.withWebview(webview => webview.focus()); } reload(): void { this.withWebview(webview => webview.reload()); } diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index 271ed303794..083550bf21d 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -73,11 +73,6 @@ export interface Webview extends IDisposable { readonly onMissingCsp: Event; sendMessage(data: any): void; - update( - html: string, - options: WebviewContentOptions, - retainContextWhenHidden: boolean - ): void; layout(): void; focus(): void; diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index b5e99945f8c..a80e6b551c0 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -194,18 +194,6 @@ export class IFrameWebview extends Disposable implements Webview { `${startQuote}${this.externalEndpoint}/vscode-resource/file${path}${endQuote}`); } - public update(html: string, options: WebviewContentOptions, retainContextWhenHidden: boolean) { - if (retainContextWhenHidden && html === this.content.html && areWebviewInputOptionsEqual(options, this.content.options)) { - return; - } - this.content = { - html: this.preprocessHtml(html), - options: options, - state: this.content.state, - }; - this.doUpdateContent(); - } - private doUpdateContent() { this._send('content', { contents: this.content.html, diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index a27ea558213..9cd4185fd76 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -497,18 +497,6 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, this.doUpdateContent(); } - public update(html: string, options: WebviewContentOptions, retainContextWhenHidden: boolean) { - if (retainContextWhenHidden && html === this.content.html && areWebviewInputOptionsEqual(options, this.content.options)) { - return; - } - this.content = { - html: html, - options: options, - state: this.content.state, - }; - this.doUpdateContent(); - } - private doUpdateContent() { this._send('content', { contents: this.content.html, From 495633ccc5a56bd13bbe9ec23a58bdc12bd129a1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Oct 2019 18:39:11 -0700 Subject: [PATCH 398/435] Make Lazy use an interface more similar to IdleValue --- src/vs/base/common/lazy.ts | 39 +++++++++---------- src/vs/base/test/common/lazy.test.ts | 10 ++--- .../contrib/codeAction/codeActionCommands.ts | 4 +- .../editor/contrib/codeAction/codeActionUi.ts | 6 +-- .../browser/customEditorInputFactory.ts | 4 +- .../customEditor/browser/customEditors.ts | 4 +- .../browser/webviewWorkbenchService.ts | 6 +-- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/vs/base/common/lazy.ts b/src/vs/base/common/lazy.ts index 7080c984a83..fe88e82bc80 100644 --- a/src/vs/base/common/lazy.ts +++ b/src/vs/base/common/lazy.ts @@ -7,28 +7,17 @@ * A value that is resolved synchronously when it is first needed. */ export interface Lazy { - /** - * True if the lazy value has been resolved. - */ + hasValue(): boolean; - /** - * Get the wrapped value. - * - * This will force evaluation of the lazy value if it has not been resolved yet. Lazy values are only - * resolved once. `getValue` will re-throw exceptions that are hit while resolving the value - */ + getValue(): T; - /** - * Create a new lazy value that is the result of applying `f` to the wrapped value. - * - * This does not force the evaluation of the current lazy value. - */ + map(f: (x: T) => R): Lazy; } -class LazyValue implements Lazy { +export class Lazy { private _didRun: boolean = false; private _value?: T; @@ -38,8 +27,17 @@ class LazyValue implements Lazy { private readonly executor: () => T, ) { } + /** + * True if the lazy value has been resolved. + */ hasValue() { return this._didRun; } + /** + * Get the wrapped value. + * + * This will force evaluation of the lazy value if it has not been resolved yet. Lazy values are only + * resolved once. `getValue` will re-throw exceptions that are hit while resolving the value + */ getValue(): T { if (!this._didRun) { try { @@ -56,11 +54,12 @@ class LazyValue implements Lazy { return this._value!; } + /** + * Create a new lazy value that is the result of applying `f` to the wrapped value. + * + * This does not force the evaluation of the current lazy value. + */ map(f: (x: T) => R): Lazy { - return new LazyValue(() => f(this.getValue())); + return new Lazy(() => f(this.getValue())); } } - -export function lazy(executor: () => T) { - return new LazyValue(executor); -} diff --git a/src/vs/base/test/common/lazy.test.ts b/src/vs/base/test/common/lazy.test.ts index 372bdca4789..ff66ec664c3 100644 --- a/src/vs/base/test/common/lazy.test.ts +++ b/src/vs/base/test/common/lazy.test.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; suite('Lazy', () => { test('lazy values should only be resolved once', () => { let counter = 0; - const value = lazy(() => ++counter); + const value = new Lazy(() => ++counter); assert.strictEqual(value.hasValue(), false); assert.strictEqual(value.getValue(), 1); @@ -20,7 +20,7 @@ suite('Lazy', () => { test('lazy values handle error case', () => { let counter = 0; - const value = lazy(() => { throw ++counter; }); + const value = new Lazy(() => { throw ++counter; }); assert.strictEqual(value.hasValue(), false); assert.throws(() => value.getValue(), 1); @@ -31,7 +31,7 @@ suite('Lazy', () => { test('map should not cause lazy values to be re-resolved', () => { let outer = 0; let inner = 10; - const outerLazy = lazy(() => ++outer); + const outerLazy = new Lazy(() => ++outer); const innerLazy = outerLazy.map(x => [x, ++inner]); assert.strictEqual(outerLazy.hasValue(), false); @@ -50,7 +50,7 @@ suite('Lazy', () => { test('map should should handle error values', () => { let outer = 0; let inner = 10; - const outerLazy = lazy(() => { throw ++outer; }); + const outerLazy = new Lazy(() => { throw ++outer; }); const innerLazy = outerLazy.map(x => { throw ++inner; }); assert.strictEqual(outerLazy.hasValue(), false); diff --git a/src/vs/editor/contrib/codeAction/codeActionCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts index c95612a7f22..07f52a6ed51 100644 --- a/src/vs/editor/contrib/codeAction/codeActionCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -5,7 +5,7 @@ import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { Lazy, lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; import { Disposable } from 'vs/base/common/lifecycle'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -67,7 +67,7 @@ export class QuickFixController extends Disposable implements IEditorContributio this._model = this._register(new CodeActionModel(this._editor, markerService, contextKeyService, progressService)); this._register(this._model.onDidChangeState(newState => this.update(newState))); - this._ui = lazy(() => + this._ui = new Lazy(() => this._register(new CodeActionUi(editor, QuickFixAction.Id, { applyCodeAction: async (action, retrigger) => { try { diff --git a/src/vs/editor/contrib/codeAction/codeActionUi.ts b/src/vs/editor/contrib/codeAction/codeActionUi.ts index 8151f035cf0..658aebe8e3a 100644 --- a/src/vs/editor/contrib/codeAction/codeActionUi.ts +++ b/src/vs/editor/contrib/codeAction/codeActionUi.ts @@ -17,7 +17,7 @@ import { CodeActionWidget } from './codeActionWidget'; import { LightBulbWidget } from './lightBulbWidget'; import { IPosition } from 'vs/editor/common/core/position'; import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; -import { Lazy, lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; export class CodeActionUi extends Disposable { @@ -36,7 +36,7 @@ export class CodeActionUi extends Disposable { ) { super(); - this._codeActionWidget = lazy(() => { + this._codeActionWidget = new Lazy(() => { return this._register(new CodeActionWidget(this._editor, contextMenuService, { onSelectCodeAction: async (action) => { this.delegate.applyCodeAction(action, /* retrigger */ true); @@ -44,7 +44,7 @@ export class CodeActionUi extends Disposable { })); }); - this._lightBulbWidget = lazy(() => { + this._lightBulbWidget = new Lazy(() => { const widget = this._register(new LightBulbWidget(this._editor, quickFixActionId, keybindingService)); this._register(widget.onClick(this._handleLightBulbSelect, this)); return widget; diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index f98e014bd68..e4509a59b02 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -10,7 +10,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; -import { lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; export class CustomEditoInputFactory extends WebviewEditorInputFactory { @@ -43,7 +43,7 @@ export class CustomEditoInputFactory extends WebviewEditorInputFactory { const data = this.fromJson(serializedEditorInput); const id = data.id || generateUuid(); - const webview = lazy(() => { + const webview = new Lazy(() => { const webviewInput = this.webviewWorkbenchService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { location: data.extensionLocation, id: data.extensionId diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 1543b72018a..36eb48e2e48 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -29,7 +29,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService'; import { CustomFileEditorInput } from './customEditorInput'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; const defaultEditorId = 'default'; @@ -169,7 +169,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ options?: { readonly customClasses: string; }, ): CustomFileEditorInput { const id = generateUuid(); - const webview = lazy(() => { + const webview = new Lazy(() => { return new UnownedDisposable(this.webviewService.createWebviewEditorOverlay(id, { customClasses: options ? options.customClasses : undefined }, {})); }); const input = this.instantiationService.createInstance(CustomFileEditorInput, resource, viewType, id, webview); diff --git a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts index 5be538dcea4..c0e1994c206 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts @@ -19,7 +19,7 @@ import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewOp import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { WebviewInput } from './webviewEditorInput'; -import { Lazy, lazy } from 'vs/base/common/lazy'; +import { Lazy } from 'vs/base/common/lazy'; export const IWebviewWorkbenchService = createDecorator('webviewEditorService'); @@ -166,7 +166,7 @@ export class WebviewEditorService implements IWebviewWorkbenchService { options: WebviewInputOptions, extension: WebviewExtensionDescription | undefined, ): WebviewInput { - const webview = lazy(() => new UnownedDisposable(this.createWebiew(id, extension, options))); + const webview = new Lazy(() => new UnownedDisposable(this.createWebiew(id, extension, options))); const webviewInput = new WebviewInput(id, viewType, title, webview); this._editorService.openEditor(webviewInput, { pinned: true, @@ -208,7 +208,7 @@ export class WebviewEditorService implements IWebviewWorkbenchService { extension: WebviewExtensionDescription | undefined, group: number | undefined, ): WebviewInput { - const webview = lazy(() => { + const webview = new Lazy(() => { const webview = this.createWebiew(id, extension, options); webview.state = state; return new UnownedDisposable(webview); From d80739df02ca956e0ac89daed5d1f2a1c6914427 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Oct 2019 13:59:16 -0700 Subject: [PATCH 399/435] Fixing TS 3.7 dom typings errors --- extensions/git/src/repository.ts | 6 +++--- src/vs/base/browser/ui/button/button.ts | 8 ++++---- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 2 +- src/vs/base/browser/ui/progressbar/progressbar.ts | 2 +- src/vs/base/browser/ui/tree/abstractTree.ts | 4 ++-- .../base/parts/quickopen/browser/quickOpenModel.ts | 2 +- src/vs/editor/contrib/rename/renameInputField.ts | 4 ++-- .../browser/parts/editor/editorDropTarget.ts | 2 +- src/vs/workbench/browser/parts/editor/editorPart.ts | 2 +- .../workbench/browser/parts/editor/editorWidgets.ts | 6 +++--- .../browser/parts/editor/tabsTitleControl.ts | 12 ++++++------ .../parts/notifications/notificationsToasts.ts | 4 ++-- .../workbench/browser/parts/quickinput/quickInput.ts | 12 ++++++------ .../contrib/debug/browser/statusbarColorProvider.ts | 2 +- .../contrib/preferences/browser/keybindingWidgets.ts | 4 ++-- .../contrib/preferences/browser/keybindingsEditor.ts | 10 +++++----- .../contrib/preferences/browser/preferencesEditor.ts | 12 ++++-------- 17 files changed, 45 insertions(+), 49 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 377851c5bcd..d37dc945f55 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1476,9 +1476,9 @@ export class Repository implements Disposable { const [refs, remotes, submodules, rebaseCommit] = await Promise.all([this.repository.getRefs({ sort }), this.repository.getRemotes(), this.repository.getSubmodules(), this.getRebaseCommit()]); this._HEAD = HEAD; - this._refs = refs; - this._remotes = remotes; - this._submodules = submodules; + this._refs = refs!; + this._remotes = remotes!; + this._submodules = submodules!; this.rebaseCommit = rebaseCommit; const index: Resource[] = []; diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index 575122ccd77..de4d35ef320 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -128,15 +128,15 @@ export class Button extends Disposable { private applyStyles(): void { if (this._element) { - const background = this.buttonBackground ? this.buttonBackground.toString() : null; + const background = this.buttonBackground ? this.buttonBackground.toString() : ''; const foreground = this.buttonForeground ? this.buttonForeground.toString() : null; - const border = this.buttonBorder ? this.buttonBorder.toString() : null; + const border = this.buttonBorder ? this.buttonBorder.toString() : ''; this._element.style.color = foreground; this._element.style.backgroundColor = background; - this._element.style.borderWidth = border ? '1px' : null; - this._element.style.borderStyle = border ? 'solid' : null; + this._element.style.borderWidth = border ? '1px' : ''; + this._element.style.borderStyle = border ? 'solid' : ''; this._element.style.borderColor = border; } } diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index b9fc4154234..0122e851bab 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -77,7 +77,7 @@ class FastLabelNode { } this._empty = empty; - this._element.style.marginLeft = empty ? '0' : null; + this._element.style.marginLeft = empty ? '0' : ''; } dispose(): void { diff --git a/src/vs/base/browser/ui/progressbar/progressbar.ts b/src/vs/base/browser/ui/progressbar/progressbar.ts index 19e16dfbe87..198d8e2310e 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.ts +++ b/src/vs/base/browser/ui/progressbar/progressbar.ts @@ -221,7 +221,7 @@ export class ProgressBar extends Disposable { protected applyStyles(): void { if (this.bit) { - const background = this.progressBarBackground ? this.progressBarBackground.toString() : null; + const background = this.progressBarBackground ? this.progressBarBackground.toString() : ''; this.bit.style.backgroundColor = background; } diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index e0376d8a519..b34dd3936a7 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -780,8 +780,8 @@ class TypeFilterController implements IDisposable { const onDragEnd = () => { this.positionClassName = positionClassName; this.domNode.className = `monaco-list-type-filter ${this.positionClassName}`; - this.domNode.style.top = null; - this.domNode.style.left = null; + this.domNode.style.top = ''; + this.domNode.style.left = ''; dispose(disposables); }; diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts index 5e1b2154cc1..9f92529bdac 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts @@ -434,7 +434,7 @@ class Renderer implements IRenderer { } } else { DOM.removeClass(groupData.container, 'results-group-separator'); - groupData.container.style.borderTopColor = null; + groupData.container.style.borderTopColor = ''; } // Group Label diff --git a/src/vs/editor/contrib/rename/renameInputField.ts b/src/vs/editor/contrib/rename/renameInputField.ts index 1113144c6c4..a87899a71a1 100644 --- a/src/vs/editor/contrib/rename/renameInputField.ts +++ b/src/vs/editor/contrib/rename/renameInputField.ts @@ -89,14 +89,14 @@ export class RenameInputField implements IContentWidget, IDisposable { const widgetShadowColor = theme.getColor(widgetShadow); const border = theme.getColor(inputBorder); - this._inputField.style.backgroundColor = background ? background.toString() : null; + this._inputField.style.backgroundColor = background ? background.toString() : ''; this._inputField.style.color = foreground ? foreground.toString() : null; this._inputField.style.borderWidth = border ? '1px' : '0px'; this._inputField.style.borderStyle = border ? 'solid' : 'none'; this._inputField.style.borderColor = border ? border.toString() : 'none'; - this._domNode!.style.boxShadow = widgetShadowColor ? ` 0 2px 8px ${widgetShadowColor}` : null; + this._domNode!.style.boxShadow = widgetShadowColor ? ` 0 2px 8px ${widgetShadowColor}` : ''; } private updateFont(): void { diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 94597ec5c07..b5089f88f4f 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -85,7 +85,7 @@ class DropOverlay extends Themable { protected updateStyles(): void { // Overlay drop background - this.overlay.style.backgroundColor = this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND); + this.overlay.style.backgroundColor = this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND) || ''; // Overlay contrast border (if any) const activeContrastBorderColor = this.getColor(activeContrastBorder); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index a3dec299bc6..9f5b31c4f55 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -796,7 +796,7 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro } updateStyles(): void { - this.container.style.backgroundColor = this.getColor(editorBackground); + this.container.style.backgroundColor = this.getColor(editorBackground) || ''; const separatorBorderStyle = { separatorBorder: this.gridSeparatorBorder, background: this.theme.getColor(EDITOR_PANE_BACKGROUND) || Color.transparent }; this.gridWidget.style(separatorBorderStyle); diff --git a/src/vs/workbench/browser/parts/editor/editorWidgets.ts b/src/vs/workbench/browser/parts/editor/editorWidgets.ts index 6616272abb1..22ca587814e 100644 --- a/src/vs/workbench/browser/parts/editor/editorWidgets.ts +++ b/src/vs/workbench/browser/parts/editor/editorWidgets.ts @@ -75,9 +75,9 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { this._domNode.style.color = foregroundColor.toString(); } - const borderColor = colors.contrastBorder ? colors.contrastBorder.toString() : null; - this._domNode.style.borderWidth = borderColor ? '1px' : null; - this._domNode.style.borderStyle = borderColor ? 'solid' : null; + const borderColor = colors.contrastBorder ? colors.contrastBorder.toString() : ''; + this._domNode.style.borderWidth = borderColor ? '1px' : ''; + this._domNode.style.borderStyle = borderColor ? 'solid' : ''; this._domNode.style.borderColor = borderColor; })); diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 2fc4adaf8db..9ff0ac17f9c 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -728,8 +728,8 @@ export class TabsTitleControl extends TitleControl { const isActiveTab = isTab && !!editor && this.group.isActive(editor); // Background - const noDNDBackgroundColor = isTab ? this.getColor(isActiveTab ? TAB_ACTIVE_BACKGROUND : TAB_INACTIVE_BACKGROUND) : null; - element.style.backgroundColor = isDND ? this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND) : noDNDBackgroundColor; + const noDNDBackgroundColor = isTab ? this.getColor(isActiveTab ? TAB_ACTIVE_BACKGROUND : TAB_INACTIVE_BACKGROUND) : ''; + element.style.backgroundColor = (isDND ? this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND) : noDNDBackgroundColor) || ''; // Outline const activeContrastBorderColor = this.getColor(activeContrastBorder); @@ -879,7 +879,7 @@ export class TabsTitleControl extends TitleControl { // Borders / Outline const borderRightColor = (this.getColor(TAB_BORDER) || this.getColor(contrastBorder)); - tabContainer.style.borderRight = borderRightColor ? `1px solid ${borderRightColor}` : null; + tabContainer.style.borderRight = borderRightColor ? `1px solid ${borderRightColor}` : ''; tabContainer.style.outlineColor = this.getColor(activeContrastBorder) || ''; // Settings @@ -934,7 +934,7 @@ export class TabsTitleControl extends TitleControl { // Container addClass(tabContainer, 'active'); tabContainer.setAttribute('aria-selected', 'true'); - tabContainer.style.backgroundColor = this.getColor(isGroupActive ? TAB_ACTIVE_BACKGROUND : TAB_UNFOCUSED_ACTIVE_BACKGROUND); + tabContainer.style.backgroundColor = this.getColor(isGroupActive ? TAB_ACTIVE_BACKGROUND : TAB_UNFOCUSED_ACTIVE_BACKGROUND) || ''; const activeTabBorderColorBottom = this.getColor(isGroupActive ? TAB_ACTIVE_BORDER : TAB_UNFOCUSED_ACTIVE_BORDER); if (activeTabBorderColorBottom) { @@ -964,8 +964,8 @@ export class TabsTitleControl extends TitleControl { // Container removeClass(tabContainer, 'active'); tabContainer.setAttribute('aria-selected', 'false'); - tabContainer.style.backgroundColor = this.getColor(TAB_INACTIVE_BACKGROUND); - tabContainer.style.boxShadow = null; + tabContainer.style.backgroundColor = this.getColor(TAB_INACTIVE_BACKGROUND) || ''; + tabContainer.style.boxShadow = ''; // Label tabLabelWidget.element.style.color = this.getColor(isGroupActive ? TAB_INACTIVE_FOREGROUND : TAB_UNFOCUSED_INACTIVE_FOREGROUND); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index d8087235f5e..863dd01c1c7 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -421,10 +421,10 @@ export class NotificationsToasts extends Themable { protected updateStyles(): void { this.mapNotificationToToast.forEach(t => { const widgetShadowColor = this.getColor(widgetShadow); - t.toast.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : null; + t.toast.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : ''; const borderColor = this.getColor(NOTIFICATIONS_TOAST_BORDER); - t.toast.style.border = borderColor ? `1px solid ${borderColor}` : null; + t.toast.style.border = borderColor ? `1px solid ${borderColor}` : ''; }); } diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.ts b/src/vs/workbench/browser/parts/quickinput/quickInput.ts index ddb957fee79..24a0b6e3202 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInput.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.ts @@ -305,8 +305,8 @@ class QuickInput extends Disposable implements IQuickInput { this.ui.inputBox.showDecoration(severity); if (severity === Severity.Error) { const styles = this.ui.inputBox.stylesForType(severity); - this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : null; - this.ui.message.style.border = styles.border ? `1px solid ${styles.border}` : null; + this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : ''; + this.ui.message.style.border = styles.border ? `1px solid ${styles.border}` : ''; this.ui.message.style.paddingBottom = '4px'; } else { this.ui.message.style.backgroundColor = ''; @@ -1511,16 +1511,16 @@ export class QuickInputService extends Component implements IQuickInputService { if (this.ui) { // TODO const titleColor = { dark: 'rgba(255, 255, 255, 0.105)', light: 'rgba(0,0,0,.06)', hc: 'black' }[theme.type]; - this.titleBar.style.backgroundColor = titleColor ? titleColor.toString() : null; + this.titleBar.style.backgroundColor = titleColor ? titleColor.toString() : ''; this.ui.inputBox.style(theme); const quickInputBackground = theme.getColor(QUICK_INPUT_BACKGROUND); - this.ui.container.style.backgroundColor = quickInputBackground ? quickInputBackground.toString() : null; + this.ui.container.style.backgroundColor = quickInputBackground ? quickInputBackground.toString() : ''; const quickInputForeground = theme.getColor(QUICK_INPUT_FOREGROUND); this.ui.container.style.color = quickInputForeground ? quickInputForeground.toString() : null; const contrastBorderColor = theme.getColor(contrastBorder); - this.ui.container.style.border = contrastBorderColor ? `1px solid ${contrastBorderColor}` : null; + this.ui.container.style.border = contrastBorderColor ? `1px solid ${contrastBorderColor}` : ''; const widgetShadowColor = theme.getColor(widgetShadow); - this.ui.container.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null; + this.ui.container.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : ''; } } diff --git a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts index 20d1d4a6a25..866505f7a91 100644 --- a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts +++ b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts @@ -66,7 +66,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri // Container Colors const backgroundColor = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_DEBUGGING_BACKGROUND, STATUS_BAR_BACKGROUND)); - container.style.backgroundColor = backgroundColor; + container.style.backgroundColor = backgroundColor || ''; container.style.color = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_DEBUGGING_FOREGROUND, STATUS_BAR_FOREGROUND)); // Border Color diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts b/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts index dd0ea57af6d..578cc39ab59 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts @@ -183,7 +183,7 @@ export class DefineKeybindingWidget extends Widget { if (colors.editorWidgetBackground) { this._domNode.domNode.style.backgroundColor = colors.editorWidgetBackground.toString(); } else { - this._domNode.domNode.style.backgroundColor = null; + this._domNode.domNode.style.backgroundColor = ''; } if (colors.editorWidgetForeground) { this._domNode.domNode.style.color = colors.editorWidgetForeground.toString(); @@ -194,7 +194,7 @@ export class DefineKeybindingWidget extends Widget { if (colors.widgetShadow) { this._domNode.domNode.style.boxShadow = `0 2px 8px ${colors.widgetShadow}`; } else { - this._domNode.domNode.style.boxShadow = null; + this._domNode.domNode.style.boxShadow = ''; } })); diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index 0437702abf9..eea6c420e1c 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -401,13 +401,13 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor const recordingBadge = DOM.append(container, DOM.$('.recording-badge.disabled')); recordingBadge.textContent = localize('recording', "Recording Keys"); this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder, badgeForeground }, colors => { - const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; - const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; - const color = colors.badgeForeground ? colors.badgeForeground.toString() : null; + const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : ''; + const color = colors.badgeForeground ? colors.badgeForeground.toString() : ''; recordingBadge.style.backgroundColor = background; - recordingBadge.style.borderWidth = border ? '1px' : null; - recordingBadge.style.borderStyle = border ? 'solid' : null; + recordingBadge.style.borderWidth = border ? '1px' : ''; + recordingBadge.style.borderStyle = border ? 'solid' : ''; recordingBadge.style.borderColor = border; recordingBadge.style.color = color ? color.toString() : null; })); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index ba32cf2dda9..2c8cfd12820 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -683,7 +683,7 @@ class PreferencesRenderersController extends Disposable { } private _updatePreference(key: string, value: any, source: ISetting, fromEditableSettings?: boolean): void { - const data: { [key: string]: any } = { + const data: { [key: string]: any; } = { userConfigurationKeys: [key] }; @@ -718,7 +718,7 @@ class PreferencesRenderersController extends Disposable { this.telemetryService.publicLog('defaultSettingsActions.copySetting', data); } - private _findSetting(filterResult: IFilterResult, key: string): { groupIdx: number, settingIdx: number, overallSettingIdx: number } | undefined { + private _findSetting(filterResult: IFilterResult, key: string): { groupIdx: number, settingIdx: number, overallSettingIdx: number; } | undefined { let overallSettingIdx = 0; for (let groupIdx = 0; groupIdx < filterResult.filteredGroups.length; groupIdx++) { @@ -826,11 +826,7 @@ class SideBySidePreferencesWidget extends Widget { this._register(attachStylerCallback(this.themeService, { scrollbarShadow }, colors => { const shadow = colors.scrollbarShadow ? colors.scrollbarShadow.toString() : null; - if (shadow) { - this.editablePreferencesEditorContainer.style.boxShadow = `-6px 0 5px -5px ${shadow}`; - } else { - this.editablePreferencesEditorContainer.style.boxShadow = null; - } + this.editablePreferencesEditorContainer.style.boxShadow = shadow ? `-6px 0 5px -5px ${shadow}` : ''; })); this.splitview.addView({ @@ -845,7 +841,7 @@ class SideBySidePreferencesWidget extends Widget { this._register(focusTracker.onDidFocus(() => this._onFocus.fire())); } - setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<{ defaultPreferencesRenderer?: IPreferencesRenderer, editablePreferencesRenderer?: IPreferencesRenderer }> { + setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<{ defaultPreferencesRenderer?: IPreferencesRenderer, editablePreferencesRenderer?: IPreferencesRenderer; }> { this.getOrCreateEditablePreferencesEditor(editablePreferencesEditorInput); this.settingsTargetsWidget.settingsTarget = this.getSettingsTarget(editablePreferencesEditorInput.getResource()!); return Promise.all([ From 11f24f64e73504688822145ef322a82362516c8a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Oct 2019 14:16:09 -0700 Subject: [PATCH 400/435] Build VS code using TS 3.7-beta Fixes #82286 --- build/package.json | 2 +- build/yarn.lock | 8 ++-- package.json | 2 +- .../electron-browser/webviewElement.ts | 37 +++++-------------- yarn.lock | 8 ++-- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/build/package.json b/build/package.json index 84556e6e17d..95c077a09f0 100644 --- a/build/package.json +++ b/build/package.json @@ -42,7 +42,7 @@ "request": "^2.85.0", "terser": "4.3.8", "tslint": "^5.9.1", - "typescript": "3.6.2", + "typescript": "3.7.0-beta", "vsce": "1.48.0", "vscode-telemetry-extractor": "^1.5.4", "xml2js": "^0.4.17" diff --git a/build/yarn.lock b/build/yarn.lock index 2451df9b537..4260a5d2823 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -2297,10 +2297,10 @@ typed-rest-client@^0.9.0: tunnel "0.0.4" underscore "1.8.3" -typescript@3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.2.tgz#105b0f1934119dde543ac8eb71af3a91009efe54" - integrity sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw== +typescript@3.7.0-beta: + version "3.7.0-beta" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-beta.tgz#4ad556e0eee14b90ecc39261001690e16e5eeba9" + integrity sha512-4jyCX+IQamrPJxgkABPq9xf+hUN+GWHVxoj+oey1TadCPa4snQl1RKwUba+1dyzYCamwlCxKvZQ3TjyWLhMGBA== typescript@^3.0.1: version "3.5.3" diff --git a/package.json b/package.json index 7f469d57bb0..b1e43d98771 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "source-map": "^0.4.4", "ts-loader": "^4.4.2", "tslint": "^5.16.0", - "typescript": "3.6", + "typescript": "3.7.0-beta", "typescript-formatter": "7.1.0", "underscore": "^1.8.2", "vinyl": "^2.0.0", diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 9cd4185fd76..4e813aeed88 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -568,7 +568,6 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, public layout(): void { // noop - } private readonly _hasFindResult = this._register(new Emitter()); @@ -630,21 +629,15 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } public showFind() { - if (this._webviewFindWidget) { - this._webviewFindWidget.reveal(); - } + this._webviewFindWidget?.reveal(); } public hideFind() { - if (this._webviewFindWidget) { - this._webviewFindWidget.hide(); - } + this._webviewFindWidget?.hide(); } public runFindAction(previous: boolean) { - if (this._webviewFindWidget) { - this._webviewFindWidget.find(previous); - } + this._webviewFindWidget?.find(previous); } public reload() { @@ -652,38 +645,26 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } public selectAll() { - if (this._webview) { - this._webview.selectAll(); - } + this._webview?.selectAll(); } public copy() { - if (this._webview) { - this._webview.copy(); - } + this._webview?.copy(); } public paste() { - if (this._webview) { - this._webview.paste(); - } + this._webview?.paste(); } public cut() { - if (this._webview) { - this._webview.cut(); - } + this._webview?.cut(); } public undo() { - if (this._webview) { - this._webview.undo(); - } + this._webview?.undo(); } public redo() { - if (this._webview) { - this._webview.redo(); - } + this._webview?.redo(); } } diff --git a/yarn.lock b/yarn.lock index 8b48f5f6231..3327954654b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8515,10 +8515,10 @@ typescript-formatter@7.1.0: commandpost "^1.0.0" editorconfig "^0.15.0" -typescript@3.6: - version "3.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.2.tgz#105b0f1934119dde543ac8eb71af3a91009efe54" - integrity sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw== +typescript@3.7.0-beta: + version "3.7.0-beta" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-beta.tgz#4ad556e0eee14b90ecc39261001690e16e5eeba9" + integrity sha512-4jyCX+IQamrPJxgkABPq9xf+hUN+GWHVxoj+oey1TadCPa4snQl1RKwUba+1dyzYCamwlCxKvZQ3TjyWLhMGBA== typescript@^2.6.2: version "2.6.2" From 9e24cb32cf98f0c85d1b8b44a10d140605fe9c3f Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 14:35:28 -0700 Subject: [PATCH 401/435] Only show active-item-indicator on activity bar, make it flush --- .../parts/activitybar/activitybarActions.ts | 4 ++-- .../parts/activitybar/media/activityaction.css | 18 ++++++++++-------- .../browser/parts/compositeBarActions.ts | 8 ++++++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 062d49bda70..37f757732cd 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -281,7 +281,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const activeBorderColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BORDER); if (activeBorderColor) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before { border-left-color: ${activeBorderColor}; } `); @@ -290,7 +290,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const activeBackgroundColor = theme.getColor(ACTIVITY_BAR_ACTIVE_BACKGROUND); if (activeBackgroundColor) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item { + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator { z-index: 0; background-color: ${activeBackgroundColor}; } diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index 2742a7e438c..eaa4f1af87a 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -22,7 +22,7 @@ font-size: 15px; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before, .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { content: ""; position: absolute; @@ -35,17 +35,17 @@ border-left: 2px solid; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before { top: 0; height: 100%; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:focus .active-item:before { +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:focus .active-item-indicator:before { border-left: none; /* don't show active border + focus at the same time, focus takes priority */ } /* Hides active elements in high contrast mode */ -.hc-black .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item { +.hc-black .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator { display: none; } @@ -53,17 +53,19 @@ border-left: none !important; /* no focus feedback when using mouse */ } -.monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, +.monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before{ + left: 0; +} + .monaco-workbench .activitybar.left > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { left: 1px; } -.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before, .monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus:before { right: 1px; } -.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item:before { +.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before { right: 2px; } @@ -73,7 +75,7 @@ outline: none; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .active-item, +.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .active-item-indicator, .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .badge { position: absolute; z-index: 1; diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 1d1b95e2464..88f5a78a1da 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -213,8 +213,12 @@ export class ActivityActionViewItem extends BaseActionViewItem { this.badge = dom.append(container, dom.$('.badge')); this.badgeContent = dom.append(this.badge, dom.$('.badge-content')); - // Active border + background - dom.append(container, dom.$('.active-item')); + // Activity bar active border + background + const isActivityBarItem = this.options.icon; + if (isActivityBarItem) { + dom.append(container, dom.$('.active-item-indicator')); + } + dom.hide(this.badge); From c72179f6c41a0b7c61c5942f404172be1a3727fa Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 10 Oct 2019 14:35:42 -0700 Subject: [PATCH 402/435] minimap - fix confusing showSlider description (#82287) Fixes https://github.com/microsoft/vscode/issues/67578 --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 5602b987afa..2b39a750360 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1833,7 +1833,7 @@ class EditorMinimap extends BaseEditorOption Date: Thu, 10 Oct 2019 14:39:45 -0700 Subject: [PATCH 403/435] Revert "Build VS code using TS 3.7-beta" This reverts commit 11f24f64e73504688822145ef322a82362516c8a. --- build/package.json | 2 +- build/yarn.lock | 8 ++-- package.json | 2 +- .../electron-browser/webviewElement.ts | 37 ++++++++++++++----- yarn.lock | 8 ++-- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/build/package.json b/build/package.json index 95c077a09f0..84556e6e17d 100644 --- a/build/package.json +++ b/build/package.json @@ -42,7 +42,7 @@ "request": "^2.85.0", "terser": "4.3.8", "tslint": "^5.9.1", - "typescript": "3.7.0-beta", + "typescript": "3.6.2", "vsce": "1.48.0", "vscode-telemetry-extractor": "^1.5.4", "xml2js": "^0.4.17" diff --git a/build/yarn.lock b/build/yarn.lock index 4260a5d2823..2451df9b537 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -2297,10 +2297,10 @@ typed-rest-client@^0.9.0: tunnel "0.0.4" underscore "1.8.3" -typescript@3.7.0-beta: - version "3.7.0-beta" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-beta.tgz#4ad556e0eee14b90ecc39261001690e16e5eeba9" - integrity sha512-4jyCX+IQamrPJxgkABPq9xf+hUN+GWHVxoj+oey1TadCPa4snQl1RKwUba+1dyzYCamwlCxKvZQ3TjyWLhMGBA== +typescript@3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.2.tgz#105b0f1934119dde543ac8eb71af3a91009efe54" + integrity sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw== typescript@^3.0.1: version "3.5.3" diff --git a/package.json b/package.json index b1e43d98771..7f469d57bb0 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "source-map": "^0.4.4", "ts-loader": "^4.4.2", "tslint": "^5.16.0", - "typescript": "3.7.0-beta", + "typescript": "3.6", "typescript-formatter": "7.1.0", "underscore": "^1.8.2", "vinyl": "^2.0.0", diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 4e813aeed88..9cd4185fd76 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -568,6 +568,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, public layout(): void { // noop + } private readonly _hasFindResult = this._register(new Emitter()); @@ -629,15 +630,21 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } public showFind() { - this._webviewFindWidget?.reveal(); + if (this._webviewFindWidget) { + this._webviewFindWidget.reveal(); + } } public hideFind() { - this._webviewFindWidget?.hide(); + if (this._webviewFindWidget) { + this._webviewFindWidget.hide(); + } } public runFindAction(previous: boolean) { - this._webviewFindWidget?.find(previous); + if (this._webviewFindWidget) { + this._webviewFindWidget.find(previous); + } } public reload() { @@ -645,26 +652,38 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, } public selectAll() { - this._webview?.selectAll(); + if (this._webview) { + this._webview.selectAll(); + } } public copy() { - this._webview?.copy(); + if (this._webview) { + this._webview.copy(); + } } public paste() { - this._webview?.paste(); + if (this._webview) { + this._webview.paste(); + } } public cut() { - this._webview?.cut(); + if (this._webview) { + this._webview.cut(); + } } public undo() { - this._webview?.undo(); + if (this._webview) { + this._webview.undo(); + } } public redo() { - this._webview?.redo(); + if (this._webview) { + this._webview.redo(); + } } } diff --git a/yarn.lock b/yarn.lock index 3327954654b..8b48f5f6231 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8515,10 +8515,10 @@ typescript-formatter@7.1.0: commandpost "^1.0.0" editorconfig "^0.15.0" -typescript@3.7.0-beta: - version "3.7.0-beta" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-beta.tgz#4ad556e0eee14b90ecc39261001690e16e5eeba9" - integrity sha512-4jyCX+IQamrPJxgkABPq9xf+hUN+GWHVxoj+oey1TadCPa4snQl1RKwUba+1dyzYCamwlCxKvZQ3TjyWLhMGBA== +typescript@3.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.2.tgz#105b0f1934119dde543ac8eb71af3a91009efe54" + integrity sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw== typescript@^2.6.2: version "2.6.2" From 4448d83f00c0c1419db2ba6254e1174cb72d61f6 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 10 Oct 2019 15:03:34 -0700 Subject: [PATCH 404/435] Update Codicons, add chrome icons and update arrows size --- .../ui/codiconLabel/codicon/codicon.css | 434 +++++++++--------- .../ui/codiconLabel/codicon/codicon.ttf | Bin 52724 -> 52860 bytes 2 files changed, 219 insertions(+), 215 deletions(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index 3b7e393ed22..134bfe6f726 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?2fe2c4c835118d85ae7b4be128fe0c1f") format("truetype"); + src: url("./codicon.ttf?815addc65cb9aac7efdb5ce4e69f9741") format("truetype"); } .codicon[class*='codicon-'] { @@ -139,217 +139,221 @@ .codicon-chevron-left:before { content: "\f122" } .codicon-chevron-right:before { content: "\f123" } .codicon-chevron-up:before { content: "\f124" } -.codicon-circle-outline:before { content: "\f125" } -.codicon-circle-slash:before { content: "\f126" } -.codicon-circuit-board:before { content: "\f127" } -.codicon-class:before { content: "\f128" } -.codicon-clear-all:before { content: "\f129" } -.codicon-clippy:before { content: "\f12a" } -.codicon-close-all:before { content: "\f12b" } -.codicon-cloud-download:before { content: "\f12c" } -.codicon-cloud-upload:before { content: "\f12d" } -.codicon-code:before { content: "\f12e" } -.codicon-collapse-all:before { content: "\f12f" } -.codicon-color-mode:before { content: "\f130" } -.codicon-color:before { content: "\f131" } -.codicon-comment-discussion:before { content: "\f132" } -.codicon-compare-changes:before { content: "\f133" } -.codicon-console:before { content: "\f134" } -.codicon-constant:before { content: "\f135" } -.codicon-continue:before { content: "\f136" } -.codicon-credit-card:before { content: "\f137" } -.codicon-current-and-breakpoint:before { content: "\f138" } -.codicon-current:before { content: "\f139" } -.codicon-dash:before { content: "\f13a" } -.codicon-dashboard:before { content: "\f13b" } -.codicon-database:before { content: "\f13c" } -.codicon-debug:before { content: "\f13d" } -.codicon-device-camera-video:before { content: "\f13e" } -.codicon-device-camera:before { content: "\f13f" } -.codicon-device-mobile:before { content: "\f140" } -.codicon-diff-added:before { content: "\f141" } -.codicon-diff-ignored:before { content: "\f142" } -.codicon-diff-modified:before { content: "\f143" } -.codicon-diff-removed:before { content: "\f144" } -.codicon-diff-renamed:before { content: "\f145" } -.codicon-diff:before { content: "\f146" } -.codicon-discard:before { content: "\f147" } -.codicon-disconnect-:before { content: "\f148" } -.codicon-editor-layout:before { content: "\f149" } -.codicon-ellipsis:before { content: "\f14a" } -.codicon-empty-window:before { content: "\f14b" } -.codicon-enumerator-member:before { content: "\f14c" } -.codicon-enumerator:before { content: "\f14d" } -.codicon-error:before { content: "\f14e" } -.codicon-event:before { content: "\f14f" } -.codicon-exclude:before { content: "\f150" } -.codicon-extensions:before { content: "\f151" } -.codicon-eye-closed:before { content: "\f152" } -.codicon-field:before { content: "\f153" } -.codicon-file-binary:before { content: "\f154" } -.codicon-file-code:before { content: "\f155" } -.codicon-file-media:before { content: "\f156" } -.codicon-file-pdf:before { content: "\f157" } -.codicon-file-submodule:before { content: "\f158" } -.codicon-file-symlink-directory:before { content: "\f159" } -.codicon-file-symlink-file:before { content: "\f15a" } -.codicon-file-zip:before { content: "\f15b" } -.codicon-files:before { content: "\f15c" } -.codicon-filter:before { content: "\f15d" } -.codicon-flame:before { content: "\f15e" } -.codicon-fold-down:before { content: "\f15f" } -.codicon-fold-up:before { content: "\f160" } -.codicon-fold:before { content: "\f161" } -.codicon-folder-active:before { content: "\f162" } -.codicon-folder-opened:before { content: "\f163" } -.codicon-folder:before { content: "\f164" } -.codicon-gear:before { content: "\f165" } -.codicon-gift:before { content: "\f166" } -.codicon-gist-secret:before { content: "\f167" } -.codicon-gist:before { content: "\f168" } -.codicon-git-commit:before { content: "\f169" } -.codicon-git-compare:before { content: "\f16a" } -.codicon-git-merge:before { content: "\f16b" } -.codicon-github-action:before { content: "\f16c" } -.codicon-github-alt:before { content: "\f16d" } -.codicon-github:before { content: "\f16e" } -.codicon-globe:before { content: "\f16f" } -.codicon-go-to-file:before { content: "\f170" } -.codicon-grabber:before { content: "\f171" } -.codicon-graph:before { content: "\f172" } -.codicon-gripper:before { content: "\f173" } -.codicon-heart:before { content: "\f174" } -.codicon-history:before { content: "\f175" } -.codicon-home:before { content: "\f176" } -.codicon-horizontal-rule:before { content: "\f177" } -.codicon-hubot:before { content: "\f178" } -.codicon-inbox:before { content: "\f179" } -.codicon-interface:before { content: "\f17a" } -.codicon-issue-closed:before { content: "\f17b" } -.codicon-issue-reopened:before { content: "\f17c" } -.codicon-issues:before { content: "\f17d" } -.codicon-italic:before { content: "\f17e" } -.codicon-jersey:before { content: "\f17f" } -.codicon-json:before { content: "\f180" } -.codicon-kebab-vertical:before { content: "\f181" } -.codicon-key:before { content: "\f182" } -.codicon-keyword:before { content: "\f183" } -.codicon-law:before { content: "\f184" } -.codicon-lightbulb-autofix:before { content: "\f185" } -.codicon-link-external:before { content: "\f186" } -.codicon-link:before { content: "\f187" } -.codicon-list-ordered:before { content: "\f188" } -.codicon-list-unordered:before { content: "\f189" } -.codicon-live-share:before { content: "\f18a" } -.codicon-loading:before { content: "\f18b" } -.codicon-location:before { content: "\f18c" } -.codicon-mail-read:before { content: "\f18d" } -.codicon-mail:before { content: "\f18e" } -.codicon-markdown:before { content: "\f18f" } -.codicon-megaphone:before { content: "\f190" } -.codicon-mention:before { content: "\f191" } -.codicon-method:before { content: "\f192" } -.codicon-milestone:before { content: "\f193" } -.codicon-misc:before { content: "\f194" } -.codicon-mortar-board:before { content: "\f195" } -.codicon-move:before { content: "\f196" } -.codicon-multiple-windows:before { content: "\f197" } -.codicon-mute:before { content: "\f198" } -.codicon-namespace:before { content: "\f199" } -.codicon-no-newline:before { content: "\f19a" } -.codicon-note:before { content: "\f19b" } -.codicon-numeric:before { content: "\f19c" } -.codicon-octoface:before { content: "\f19d" } -.codicon-open-preview:before { content: "\f19e" } -.codicon-operator:before { content: "\f19f" } -.codicon-package:before { content: "\f1a0" } -.codicon-paintcan:before { content: "\f1a1" } -.codicon-parameter:before { content: "\f1a2" } -.codicon-pause:before { content: "\f1a3" } -.codicon-pin:before { content: "\f1a4" } -.codicon-play:before { content: "\f1a5" } -.codicon-plug:before { content: "\f1a6" } -.codicon-preserve-case:before { content: "\f1a7" } -.codicon-preview:before { content: "\f1a8" } -.codicon-project:before { content: "\f1a9" } -.codicon-property:before { content: "\f1aa" } -.codicon-pulse:before { content: "\f1ab" } -.codicon-question:before { content: "\f1ac" } -.codicon-quote:before { content: "\f1ad" } -.codicon-radio-tower:before { content: "\f1ae" } -.codicon-reactions:before { content: "\f1af" } -.codicon-references:before { content: "\f1b0" } -.codicon-refresh:before { content: "\f1b1" } -.codicon-regex:before { content: "\f1b2" } -.codicon-remote:before { content: "\f1b3" } -.codicon-remove:before { content: "\f1b4" } -.codicon-replace-all:before { content: "\f1b5" } -.codicon-replace:before { content: "\f1b6" } -.codicon-repo-clone:before { content: "\f1b7" } -.codicon-repo-force-push:before { content: "\f1b8" } -.codicon-repo-pull:before { content: "\f1b9" } -.codicon-repo-push:before { content: "\f1ba" } -.codicon-report:before { content: "\f1bb" } -.codicon-request-changes:before { content: "\f1bc" } -.codicon-restart:before { content: "\f1bd" } -.codicon-rocket:before { content: "\f1be" } -.codicon-root-folder-opened:before { content: "\f1bf" } -.codicon-root-folder:before { content: "\f1c0" } -.codicon-rss:before { content: "\f1c1" } -.codicon-ruby:before { content: "\f1c2" } -.codicon-ruler:before { content: "\f1c3" } -.codicon-save-all:before { content: "\f1c4" } -.codicon-save-as:before { content: "\f1c5" } -.codicon-save:before { content: "\f1c6" } -.codicon-screen-full:before { content: "\f1c7" } -.codicon-screen-normal:before { content: "\f1c8" } -.codicon-search-stop:before { content: "\f1c9" } -.codicon-selection:before { content: "\f1ca" } -.codicon-server:before { content: "\f1cb" } -.codicon-settings:before { content: "\f1cc" } -.codicon-shield:before { content: "\f1cd" } -.codicon-smiley:before { content: "\f1ce" } -.codicon-snippet:before { content: "\f1cf" } -.codicon-sort-precedence:before { content: "\f1d0" } -.codicon-split-horizontal:before { content: "\f1d1" } -.codicon-split-vertical:before { content: "\f1d2" } -.codicon-squirrel:before { content: "\f1d3" } -.codicon-star-empty:before { content: "\f1d4" } -.codicon-star-full:before { content: "\f1d5" } -.codicon-star-half:before { content: "\f1d6" } -.codicon-start:before { content: "\f1d7" } -.codicon-step-into:before { content: "\f1d8" } -.codicon-step-out:before { content: "\f1d9" } -.codicon-step-over:before { content: "\f1da" } -.codicon-string:before { content: "\f1db" } -.codicon-structure:before { content: "\f1dc" } -.codicon-tasklist:before { content: "\f1dd" } -.codicon-telescope:before { content: "\f1de" } -.codicon-text-size:before { content: "\f1df" } -.codicon-three-bars:before { content: "\f1e0" } -.codicon-thumbsdown:before { content: "\f1e1" } -.codicon-thumbsup:before { content: "\f1e2" } -.codicon-tools:before { content: "\f1e3" } -.codicon-trash:before { content: "\f1e4" } -.codicon-triangle-down:before { content: "\f1e5" } -.codicon-triangle-left:before { content: "\f1e6" } -.codicon-triangle-right:before { content: "\f1e7" } -.codicon-triangle-up:before { content: "\f1e8" } -.codicon-twitter:before { content: "\f1e9" } -.codicon-unfold:before { content: "\f1ea" } -.codicon-unlock:before { content: "\f1eb" } -.codicon-unmute:before { content: "\f1ec" } -.codicon-unverified:before { content: "\f1ed" } -.codicon-variable:before { content: "\f1ee" } -.codicon-verified:before { content: "\f1ef" } -.codicon-versions:before { content: "\f1f0" } -.codicon-vm-active:before { content: "\f1f1" } -.codicon-vm-outline:before { content: "\f1f2" } -.codicon-vm-running:before { content: "\f1f3" } -.codicon-watch:before { content: "\f1f4" } -.codicon-whitespace:before { content: "\f1f5" } -.codicon-whole-word:before { content: "\f1f6" } -.codicon-window:before { content: "\f1f7" } -.codicon-word-wrap:before { content: "\f1f8" } -.codicon-zoom-in:before { content: "\f1f9" } -.codicon-zoom-out:before { content: "\f1fa" } +.codicon-chrome-close:before { content: "\f125" } +.codicon-chrome-maximize:before { content: "\f126" } +.codicon-chrome-minimize:before { content: "\f127" } +.codicon-chrome-restore:before { content: "\f128" } +.codicon-circle-outline:before { content: "\f129" } +.codicon-circle-slash:before { content: "\f12a" } +.codicon-circuit-board:before { content: "\f12b" } +.codicon-class:before { content: "\f12c" } +.codicon-clear-all:before { content: "\f12d" } +.codicon-clippy:before { content: "\f12e" } +.codicon-close-all:before { content: "\f12f" } +.codicon-cloud-download:before { content: "\f130" } +.codicon-cloud-upload:before { content: "\f131" } +.codicon-code:before { content: "\f132" } +.codicon-collapse-all:before { content: "\f133" } +.codicon-color-mode:before { content: "\f134" } +.codicon-color:before { content: "\f135" } +.codicon-comment-discussion:before { content: "\f136" } +.codicon-compare-changes:before { content: "\f137" } +.codicon-console:before { content: "\f138" } +.codicon-constant:before { content: "\f139" } +.codicon-continue:before { content: "\f13a" } +.codicon-credit-card:before { content: "\f13b" } +.codicon-current-and-breakpoint:before { content: "\f13c" } +.codicon-current:before { content: "\f13d" } +.codicon-dash:before { content: "\f13e" } +.codicon-dashboard:before { content: "\f13f" } +.codicon-database:before { content: "\f140" } +.codicon-debug:before { content: "\f141" } +.codicon-device-camera-video:before { content: "\f142" } +.codicon-device-camera:before { content: "\f143" } +.codicon-device-mobile:before { content: "\f144" } +.codicon-diff-added:before { content: "\f145" } +.codicon-diff-ignored:before { content: "\f146" } +.codicon-diff-modified:before { content: "\f147" } +.codicon-diff-removed:before { content: "\f148" } +.codicon-diff-renamed:before { content: "\f149" } +.codicon-diff:before { content: "\f14a" } +.codicon-discard:before { content: "\f14b" } +.codicon-disconnect-:before { content: "\f14c" } +.codicon-editor-layout:before { content: "\f14d" } +.codicon-ellipsis:before { content: "\f14e" } +.codicon-empty-window:before { content: "\f14f" } +.codicon-enumerator-member:before { content: "\f150" } +.codicon-enumerator:before { content: "\f151" } +.codicon-error:before { content: "\f152" } +.codicon-event:before { content: "\f153" } +.codicon-exclude:before { content: "\f154" } +.codicon-extensions:before { content: "\f155" } +.codicon-eye-closed:before { content: "\f156" } +.codicon-field:before { content: "\f157" } +.codicon-file-binary:before { content: "\f158" } +.codicon-file-code:before { content: "\f159" } +.codicon-file-media:before { content: "\f15a" } +.codicon-file-pdf:before { content: "\f15b" } +.codicon-file-submodule:before { content: "\f15c" } +.codicon-file-symlink-directory:before { content: "\f15d" } +.codicon-file-symlink-file:before { content: "\f15e" } +.codicon-file-zip:before { content: "\f15f" } +.codicon-files:before { content: "\f160" } +.codicon-filter:before { content: "\f161" } +.codicon-flame:before { content: "\f162" } +.codicon-fold-down:before { content: "\f163" } +.codicon-fold-up:before { content: "\f164" } +.codicon-fold:before { content: "\f165" } +.codicon-folder-active:before { content: "\f166" } +.codicon-folder-opened:before { content: "\f167" } +.codicon-folder:before { content: "\f168" } +.codicon-gear:before { content: "\f169" } +.codicon-gift:before { content: "\f16a" } +.codicon-gist-secret:before { content: "\f16b" } +.codicon-gist:before { content: "\f16c" } +.codicon-git-commit:before { content: "\f16d" } +.codicon-git-compare:before { content: "\f16e" } +.codicon-git-merge:before { content: "\f16f" } +.codicon-github-action:before { content: "\f170" } +.codicon-github-alt:before { content: "\f171" } +.codicon-github:before { content: "\f172" } +.codicon-globe:before { content: "\f173" } +.codicon-go-to-file:before { content: "\f174" } +.codicon-grabber:before { content: "\f175" } +.codicon-graph:before { content: "\f176" } +.codicon-gripper:before { content: "\f177" } +.codicon-heart:before { content: "\f178" } +.codicon-history:before { content: "\f179" } +.codicon-home:before { content: "\f17a" } +.codicon-horizontal-rule:before { content: "\f17b" } +.codicon-hubot:before { content: "\f17c" } +.codicon-inbox:before { content: "\f17d" } +.codicon-interface:before { content: "\f17e" } +.codicon-issue-closed:before { content: "\f17f" } +.codicon-issue-reopened:before { content: "\f180" } +.codicon-issues:before { content: "\f181" } +.codicon-italic:before { content: "\f182" } +.codicon-jersey:before { content: "\f183" } +.codicon-json:before { content: "\f184" } +.codicon-kebab-vertical:before { content: "\f185" } +.codicon-key:before { content: "\f186" } +.codicon-keyword:before { content: "\f187" } +.codicon-law:before { content: "\f188" } +.codicon-lightbulb-autofix:before { content: "\f189" } +.codicon-link-external:before { content: "\f18a" } +.codicon-link:before { content: "\f18b" } +.codicon-list-ordered:before { content: "\f18c" } +.codicon-list-unordered:before { content: "\f18d" } +.codicon-live-share:before { content: "\f18e" } +.codicon-loading:before { content: "\f18f" } +.codicon-location:before { content: "\f190" } +.codicon-mail-read:before { content: "\f191" } +.codicon-mail:before { content: "\f192" } +.codicon-markdown:before { content: "\f193" } +.codicon-megaphone:before { content: "\f194" } +.codicon-mention:before { content: "\f195" } +.codicon-method:before { content: "\f196" } +.codicon-milestone:before { content: "\f197" } +.codicon-misc:before { content: "\f198" } +.codicon-mortar-board:before { content: "\f199" } +.codicon-move:before { content: "\f19a" } +.codicon-multiple-windows:before { content: "\f19b" } +.codicon-mute:before { content: "\f19c" } +.codicon-namespace:before { content: "\f19d" } +.codicon-no-newline:before { content: "\f19e" } +.codicon-note:before { content: "\f19f" } +.codicon-numeric:before { content: "\f1a0" } +.codicon-octoface:before { content: "\f1a1" } +.codicon-open-preview:before { content: "\f1a2" } +.codicon-operator:before { content: "\f1a3" } +.codicon-package:before { content: "\f1a4" } +.codicon-paintcan:before { content: "\f1a5" } +.codicon-parameter:before { content: "\f1a6" } +.codicon-pause:before { content: "\f1a7" } +.codicon-pin:before { content: "\f1a8" } +.codicon-play:before { content: "\f1a9" } +.codicon-plug:before { content: "\f1aa" } +.codicon-preserve-case:before { content: "\f1ab" } +.codicon-preview:before { content: "\f1ac" } +.codicon-project:before { content: "\f1ad" } +.codicon-property:before { content: "\f1ae" } +.codicon-pulse:before { content: "\f1af" } +.codicon-question:before { content: "\f1b0" } +.codicon-quote:before { content: "\f1b1" } +.codicon-radio-tower:before { content: "\f1b2" } +.codicon-reactions:before { content: "\f1b3" } +.codicon-references:before { content: "\f1b4" } +.codicon-refresh:before { content: "\f1b5" } +.codicon-regex:before { content: "\f1b6" } +.codicon-remote:before { content: "\f1b7" } +.codicon-remove:before { content: "\f1b8" } +.codicon-replace-all:before { content: "\f1b9" } +.codicon-replace:before { content: "\f1ba" } +.codicon-repo-clone:before { content: "\f1bb" } +.codicon-repo-force-push:before { content: "\f1bc" } +.codicon-repo-pull:before { content: "\f1bd" } +.codicon-repo-push:before { content: "\f1be" } +.codicon-report:before { content: "\f1bf" } +.codicon-request-changes:before { content: "\f1c0" } +.codicon-restart:before { content: "\f1c1" } +.codicon-rocket:before { content: "\f1c2" } +.codicon-root-folder-opened:before { content: "\f1c3" } +.codicon-root-folder:before { content: "\f1c4" } +.codicon-rss:before { content: "\f1c5" } +.codicon-ruby:before { content: "\f1c6" } +.codicon-ruler:before { content: "\f1c7" } +.codicon-save-all:before { content: "\f1c8" } +.codicon-save-as:before { content: "\f1c9" } +.codicon-save:before { content: "\f1ca" } +.codicon-screen-full:before { content: "\f1cb" } +.codicon-screen-normal:before { content: "\f1cc" } +.codicon-search-stop:before { content: "\f1cd" } +.codicon-selection:before { content: "\f1ce" } +.codicon-server:before { content: "\f1cf" } +.codicon-settings:before { content: "\f1d0" } +.codicon-shield:before { content: "\f1d1" } +.codicon-smiley:before { content: "\f1d2" } +.codicon-snippet:before { content: "\f1d3" } +.codicon-sort-precedence:before { content: "\f1d4" } +.codicon-split-horizontal:before { content: "\f1d5" } +.codicon-split-vertical:before { content: "\f1d6" } +.codicon-squirrel:before { content: "\f1d7" } +.codicon-star-empty:before { content: "\f1d8" } +.codicon-star-full:before { content: "\f1d9" } +.codicon-star-half:before { content: "\f1da" } +.codicon-start:before { content: "\f1db" } +.codicon-step-into:before { content: "\f1dc" } +.codicon-step-out:before { content: "\f1dd" } +.codicon-step-over:before { content: "\f1de" } +.codicon-string:before { content: "\f1df" } +.codicon-structure:before { content: "\f1e0" } +.codicon-tasklist:before { content: "\f1e1" } +.codicon-telescope:before { content: "\f1e2" } +.codicon-text-size:before { content: "\f1e3" } +.codicon-three-bars:before { content: "\f1e4" } +.codicon-thumbsdown:before { content: "\f1e5" } +.codicon-thumbsup:before { content: "\f1e6" } +.codicon-tools:before { content: "\f1e7" } +.codicon-trash:before { content: "\f1e8" } +.codicon-triangle-down:before { content: "\f1e9" } +.codicon-triangle-left:before { content: "\f1ea" } +.codicon-triangle-right:before { content: "\f1eb" } +.codicon-triangle-up:before { content: "\f1ec" } +.codicon-twitter:before { content: "\f1ed" } +.codicon-unfold:before { content: "\f1ee" } +.codicon-unlock:before { content: "\f1ef" } +.codicon-unmute:before { content: "\f1f0" } +.codicon-unverified:before { content: "\f1f1" } +.codicon-variable:before { content: "\f1f2" } +.codicon-verified:before { content: "\f1f3" } +.codicon-versions:before { content: "\f1f4" } +.codicon-vm-active:before { content: "\f1f5" } +.codicon-vm-outline:before { content: "\f1f6" } +.codicon-vm-running:before { content: "\f1f7" } +.codicon-watch:before { content: "\f1f8" } +.codicon-whitespace:before { content: "\f1f9" } +.codicon-whole-word:before { content: "\f1fa" } +.codicon-window:before { content: "\f1fb" } +.codicon-word-wrap:before { content: "\f1fc" } +.codicon-zoom-in:before { content: "\f1fd" } +.codicon-zoom-out:before { content: "\f1fe" } diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf index ad7cb8ed77a373322a12b362f1e01d1f2dc1663d..2040fb440c846396988498821760586caee729b0 100644 GIT binary patch delta 3984 zcmY+H3tUuH9>;&@4#Mze7=||t!!UrzLm6NYa0V0w5fL%j9zH@vQ9*p=YsE2bEnQRG z(Q;QKvU00+&BCl*(X~=U*UU<7%SV*u+O5pfYV|R=?*DLXw+6oV-2c7j{?EDh{QkeW zb90BTcc-q^>YfI$jR0z=H`UF5@+sQ{zMbuumplv{K1&_^<~J`|?3a|c1vt_J1n%6@X?4YeQD36b;rGMT;G$db z*IlC{_~_V#?|*LZ+_^Jc_oXhEVm%ablsQ9R$7obw3@R}eRTzhAj7JUb!9>*JH@Fw~;eI@TNtleO zco21%hUu7rdd$Qu%*GtdMI)Nrn1^P}#{w+GA}pqE4`B(GVmVgew^)f5tb!Y>@i5k4 zEgr$|unv!5JvQL?*oeom37gT1E%*aG*oG(YB(~#^_!D;EDYW5fwBs4+<5RuD+z1e|30x+&LOX!^poFvm zwN8Sq)Kbj|ND)w{OGq0~XGlmTQ0pb67pOBOq#UTTB%~pz4H8llRQGJ!5F{+9b0sLG zmgFcPu|aK;knEt&laK(RHcLo~Q0GfXlu#E)NS;s^N=T?s7fDF6P^mZtZc;DQha{w9 zs7oZIXsAmiq;06;?!;3nqjtFj!PKshkn*AaRzfuZb)|%=0cwkc>H_L22~`N)J&a-l zDi)}#CD_xk(ElK_r2srxLKOrqVuET3T*L&@JT-w?wk(P=Bvf7CnG&iqaB+@6wr4l> zbWoHdp~?d%?+{Q8g6Bz4;JF<*)i#16mxQVjyjVhY30@+>D9@^(skU(xRY<5p!N*9b zR>3PJsPQPl6KwZWbdQAU7JQ%eI}OO%gH@@XZpk6L67* zzz$D#XqLO3qHPi~81N?~WHsPVO2~A;MMi?`2V7(%$cVs2MuIE}e20Y034Eu7Yzq7- z2^ki6n}n=0PfN(K!9{k0tQ%ZpC&r1BB&?0I{0cx zY)E;?-jFjPw+#t~YQsXqcEg!auh1o-ZK0=)0mcI3O5@S6oUln@H%$emHj^42AHFKQ zGa@|ViHNI_1(9pqk=LWrqNYTxhz^O)iM}^_MfCeIK{2Huc=uO=x;!;@aHdD&`g>uf#A?a7x@s#7+l^rlWp z-IaQJV8y^6(*~!t4Jsb=+@PNHfb{J2N$J}&{4$C&=4Twp^v-k-&s>+;ouy>uXU)lK z&r%0R4<0r6?2z;!-Pz~uq4st5F8jrt>YR-^?KzioQ*#?~AIaUHm!4Ohcghjs*p(la zzbgOxp`}9`hi)3Wv!JoyvqHbZ*23#WONy=zD;?H8?5s1yS?fIFN_Dlmx?DGkV~Zyh zzf^p-B%q|Cw?53))swq|b zs;-VpAGdN`*SN2%L#k`5H;wlipFCcxsi^rt4d*Y}EP&v!UrMKV9o{X{1pahu*b4&&KY} z`rnj%nUzH_gWbS%(|*qHVmjvjRi2L3am?SX&^#-3*K|4X7hn3mEW(#Ld|8Sw^GUH7 zEbNeW#lhlOoI|_PzoD>Qcda*)75AU`)!7ewBjxM5E<;(40pc#0#cHq^d?=H0T?=q3 z3tUSiyJpsQ*w>;^atEU+4hdFxv$!6W>+L`&DD*L8A-)iF^q+HYe!qm zQ_NKkYx2P4vIu`$lrbU5C&p$~ZWxByH;fuwWc(IldS!{DO zj!W>@rxc7z9+aA>9h)(Q(ztwsqu&lTM%zr*_ox&yPEW z-e9w+cB}@wMck)7!ZhG+YorzRvD4$H)@FC)rdWMUqMwi5WWC^Wv6k+rsO~83<^JYl zr}*5a!`F{TMIDdY=@K91b*($m8JFO^V2*T|%`SGX<+irIv$NA&Xf_urMs5A=mX6-G zH!bvoa-ZJZap{Oj(JQe^oD#2?JHC7CLsk?pywt#^y!!!FL1t#XGxc_KN?< Zv*-24L3htDtY5Uad0~CWiKByj{|h&SeAfT~ delta 3833 zcmZ9P33yc1703T~CYdG4?3tNt%w%RVOV$Y_Gn0^&H6aNhETI%BOV}c7L=@2KAW&RN z2|5@nMnzOaM2bc&3Z^Iss9;kXD}o|YYw^{pSCJx;q37j(ZNHlD`^|gjy?f8OFYkZ; zbLU#O^3o&9EuQF1fNcUWb?(wR9r(n}0aX)VJhyPknguT=NJD}2dBD>J?epi%vu!>% zjmDlQ!tHcH?M!H<^MgcA`_h%G$F*G_pnRVJ3GGXk&zzm(E$;p$Oqa zx}QelvzN_TI^Xqd#)!Ls-YqmBsbl%gE8pLHp$s_G4d|xbf6!Bt0Y+nqq>`u7XBjHL zN3!xFUBQQkPu}^TC86rd1AD8^6>LkUU|LKtNz z$8c1j5>=>14Qeq0BQY9dFcx*F$2c^g5ltA6X0%`;CSfwBpcPZ`GfczJaRX-H7nq4z zn2kAT!(7bA0xU#3Zp0!i#u6-zVi}gBgNEIN6}TC<;8v`{YOKL+xE;U59k>%wti@ee zhYk1@HsWsFgL`owevM7|4K||__u~P?uoVxY3lHI8Y{Mhy#-n%)kK+kEiKp;1cG8Sz zu^Z1}51z+f?86Iq5j}{$j92h`?8mD(Kx%m%z4!wT;SC(d5xj+?IELeR8}H%--oqd9 zC!E5c(U14>7kq%zq?t1~i;wUz&fyb$iVOHFKEvN}5ntdR_!9rbSNIy=fa6A#5D{cj_VAuUX9CSVX4f@Y|PHmSURag6=T|~F{4%+O_2qotCv4z)d13L0VxC0 z905qAQk#JE0BNp(lmUr!BSRX2G+#h!fwVwCx`DJ%Knj9HT_HnSf^=h4{-9tx9Ty7_ zq2m$(Ne$9cf!uo1G6BgC(sBU_5mJYMBnjyz0f`gR3IWL!(#--AEF^ic1fuKdz0retyt$?}`e1rgXu`U|fLQ#W&`V+iS zK%ELsUMhphu?)jx?+p}95m48Hw+g5+!KVr^GxmU?&Pyud@>PPm8Jv7thWZ+OmH_Rs zxM6XtJc{HaL+uT|NI;DaPI8i=mIo&}$x!oylbmG82Ea*9GGqwg%LP~+>oubh%h?ICA#gc6L52h_XD7&-z`F%x zQs9pY$gaR26OeI%KMusMm`$zw=v-b0K~@G%N|qs01DDrCkiCJ+Ya;M69pyC<og4tpYyDzrVJ~8@|`b$ljW{>8QHcxwx_PF*!(%7UuNvD!k$z{nGQvxY1Dg7yz zbPipaZjo+>?x?O`zes<^&|%nVIAts|PB(5a?lzt=UNgB((@mSrFbB-j%w6Uq7L}#h z(rfuV_0H5I)_`@Tb(c+J8*AHc&$f5ikEErftxnsX)}QuGG<{?G?)3N4zsac2*pTsB zW@+YytZ>%4A?6`_9hHu?&am@Jc31ZK>`Sg{*8g?b6d{w zoNL~xKAUff-{GI(eP@rsW>Zjpr@N*XOUu-IR7Y!dieBbcX6*DUiR*tTGsmffntZGNqx$2zi z&DED{X4Y)2>8+7!^J-Vu?x;O8B5lNm5eG+{9$7!~#Hf~0TcV@-Mvoo6VRYY^wlN#W z>>Arwr?1Pan^w1^uB-0N`h@z7`fc@R#ubg*H13rKRYO_Bl!pC{8I7l!Qk#5DWlarD zGn#tGtHxK3-`bqfJg@nc<}W70xD?;xe>ABsMF{8a)+1#>xxg1BxF95}A@_GT{2#%10Cn zz*7p;_{rv&!9yHS(N97Gi4Vvbvb!CRRQ; zW*|}VV|>6%g;;rEe4si$Fj$B7$g%IT_69f7l0FmVJhYiHm6({ajV4lw!TjtwRu(^A z$PxzgTx`$MN8Pk2Gnz>M1kl6WfHd0MPQ+~5 zK*DQ_*us%&<`4V)MNI8htJEQnsU&2xgzdv@cAMI!)-$)y?~8ALv$&WK%=kuxmWrqPct z_8E)@XTaujCTS`ZMuV}yp~y&anvzmAI$fr-R-qY^9n95aIlLB6N;FH!^aj1x>dMMY z_W0bjMU>i>f3JnHtcvQNCv#K>&r_zU}n#_j+PMw~q)q20dsML0+FqW2BpK4=Nw$PSV zXf_%dGn*O`j4ZQcl*d&wl)jUuw6}(v66k$5DK9EZVW$n{So+NXX1A*CYQNg!SNkLW zP{bdxM@sAwyD}0AvWQeA`bm<;s~WX33dnRdoK4W($O}^6TBE>eiNRDM{80y)DP6apuvsu&4I% cH(d1l?~umdllz8F(Nlf+1J*O~t$gjj0YM)e(EtDd From 5fe2dad8b20cbd0118c11d0b19fc7b38b1fd286c Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 10 Oct 2019 15:10:35 -0700 Subject: [PATCH 405/435] minimap - invalidate cache to ensure colors are updated on theme change Fixes https://github.com/microsoft/vscode/issues/78398 --- src/vs/editor/common/viewModel/viewModelImpl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index a99279b51d0..544a115ecf1 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -129,6 +129,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel super.dispose(); this.decorations.dispose(); this.lines.dispose(); + this.invalidateMinimapColorCache(); this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); } From 72bc289d32ec4f867e73b7f1f2a22f7d614ae2bb Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 10 Oct 2019 15:20:01 -0700 Subject: [PATCH 406/435] Fixing unit tests --- src/vs/base/test/common/lazy.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/base/test/common/lazy.test.ts b/src/vs/base/test/common/lazy.test.ts index ff66ec664c3..c6a1655513f 100644 --- a/src/vs/base/test/common/lazy.test.ts +++ b/src/vs/base/test/common/lazy.test.ts @@ -20,12 +20,12 @@ suite('Lazy', () => { test('lazy values handle error case', () => { let counter = 0; - const value = new Lazy(() => { throw ++counter; }); + const value = new Lazy(() => { throw new Error(`${++counter}`); }); assert.strictEqual(value.hasValue(), false); - assert.throws(() => value.getValue(), 1); + assert.throws(() => value.getValue(), /\b1\b/); assert.strictEqual(value.hasValue(), true); - assert.throws(() => value.getValue(), 1); + assert.throws(() => value.getValue(), /\b1\b/); }); test('map should not cause lazy values to be re-resolved', () => { @@ -50,15 +50,15 @@ suite('Lazy', () => { test('map should should handle error values', () => { let outer = 0; let inner = 10; - const outerLazy = new Lazy(() => { throw ++outer; }); - const innerLazy = outerLazy.map(x => { throw ++inner; }); + const outerLazy = new Lazy(() => { throw new Error(`${++outer}`); }); + const innerLazy = outerLazy.map(x => { throw new Error(`${++inner}`); }); assert.strictEqual(outerLazy.hasValue(), false); assert.strictEqual(innerLazy.hasValue(), false); - assert.throws(() => innerLazy.getValue(), 1); // we should get result from outer + assert.throws(() => innerLazy.getValue(), /\b1\b/); // we should get result from outer assert.strictEqual(outerLazy.hasValue(), true); assert.strictEqual(innerLazy.hasValue(), true); - assert.throws(() => outerLazy.getValue(), 1); + assert.throws(() => outerLazy.getValue(), /\b1\b/); }); }); From 95ebd1a17d6b1e30f54d18781e81c2f47fa33082 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Oct 2019 10:01:07 +0200 Subject: [PATCH 407/435] Fixes #49693: Disable column selection with middle mouse button if selection clipboard is enabled on Linux --- src/vs/editor/browser/view/viewController.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 3cbd1cc286f..9057fdfbe22 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -13,6 +13,7 @@ import { IConfiguration } from 'vs/editor/common/editorCommon'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import * as platform from 'vs/base/common/platform'; export interface IMouseDispatchData { position: Position; @@ -132,7 +133,8 @@ export class ViewController { } public dispatchMouse(data: IMouseDispatchData): void { - if (data.middleButton) { + const selectionClipboardIsOn = (platform.isLinux && this.configuration.options.get(EditorOption.selectionClipboard)); + if (data.middleButton && !selectionClipboardIsOn) { this._columnSelect(data.position, data.mouseColumn, data.inSelectionMode); } else if (data.startedOnLineNumbers) { // If the dragging started on the gutter, then have operations work on the entire line From 59abaab72831c4b43fd259e73b381f77168926f8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Oct 2019 11:13:27 +0200 Subject: [PATCH 408/435] Fixes #75345: Do not write to the selection clipboard when restoring selection state --- .../contrib/codeEditor/browser/selectionClipboard.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts index 82057e3a115..5d7a143aa98 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/selectionClipboard.ts @@ -77,6 +77,11 @@ export class SelectionClipboard extends Disposable implements IEditorContributio if (!isEnabled) { return; } + if (e.source === 'restoreState') { + // do not set selection to clipboard if this selection change + // was caused by restoring editors... + return; + } setSelectionToClipboard.schedule(); })); } From be89df857d05bf8fdddd7d9cc9aeff925c424f76 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 11:24:21 +0200 Subject: [PATCH 409/435] Add busy tasks and check busy tasks in debug to prevent 'stale' prelaunch task results Fixes #82076 --- .../contrib/debug/browser/debugService.ts | 35 +++++++++++-------- .../tasks/browser/abstractTaskService.ts | 7 ++++ .../tasks/browser/terminalTaskSystem.ts | 25 ++++++++++++- .../contrib/tasks/common/taskService.ts | 1 + .../contrib/tasks/common/taskSystem.ts | 1 + .../contrib/tasks/node/processTaskSystem.ts | 4 +++ 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 15ed577b5ab..6b15aedcf4d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -768,9 +768,27 @@ export class DebugService implements IDebugService { // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 let taskStarted = false; - const promise: Promise = this.taskService.getActiveTasks().then(tasks => { + const inactivePromise: Promise = new Promise((c, e) => once(e => { + // When a task isBackground it will go inactive when it is safe to launch. + // But when a background task is terminated by the user, it will also fire an inactive event. + // This means that we will not get to see the real exit code from running the task (undefined when terminated by the user). + // Catch the ProcessEnded event here, which occurs before inactive, and capture the exit code to prevent this. + return (e.kind === TaskEventKind.Inactive + || (e.kind === TaskEventKind.ProcessEnded && e.exitCode === undefined)) + && e.taskId === task._id; + }, this.taskService.onDidStateChange)(e => { + taskStarted = true; + c(e.kind === TaskEventKind.ProcessEnded ? { exitCode: e.exitCode } : null); + })); + + const promise: Promise = this.taskService.getActiveTasks().then(async (tasks): Promise => { if (tasks.filter(t => t._id === task._id).length) { - // task is already running - nothing to do. + // Check that the task isn't busy and if it is, wait for it + const busyTasks = await this.taskService.getBusyTasks(); + if (busyTasks.filter(t => t._id === task._id).length) { + return inactivePromise; + } + // task is already running and isn't busy - nothing to do. return Promise.resolve(null); } once(e => ((e.kind === TaskEventKind.Active) || (e.kind === TaskEventKind.DependsOnStarted)) && e.taskId === task._id, this.taskService.onDidStateChange)(() => { @@ -780,18 +798,7 @@ export class DebugService implements IDebugService { }); const taskPromise = this.taskService.run(task); if (task.configurationProperties.isBackground) { - return new Promise((c, e) => once(e => { - // When a task isBackground it will go inactive when it is safe to launch. - // But when a background task is terminated by the user, it will also fire an inactive event. - // This means that we will not get to see the real exit code from running the task (undefined when terminated by the user). - // Catch the ProcessEnded event here, which occurs before inactive, and capture the exit code to prevent this. - return (e.kind === TaskEventKind.Inactive - || (e.kind === TaskEventKind.ProcessEnded && e.exitCode === undefined)) - && e.taskId === task._id; - }, this.taskService.onDidStateChange)(e => { - taskStarted = true; - c(e.kind === TaskEventKind.ProcessEnded ? { exitCode: e.exitCode } : null); - })); + return inactivePromise; } return taskPromise; diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 339485761d6..c5dd5a080c9 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -569,6 +569,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return Promise.resolve(this._taskSystem.getActiveTasks()); } + public getBusyTasks(): Promise { + if (!this._taskSystem) { + return Promise.resolve([]); + } + return Promise.resolve(this._taskSystem.getBusyTasks()); + } + public getRecentlyUsedTasks(): LinkedMap { if (this._recentlyUsedTasks) { return this._recentlyUsedTasks; diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 4f33f892c3f..bf87275c1cc 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -152,6 +152,7 @@ export class TerminalTaskSystem implements ITaskSystem { }; private activeTasks: IStringDictionary; + private busyTasks: IStringDictionary; private terminals: IStringDictionary; private idleTaskTerminals: LinkedMap; private sameTaskTerminals: IStringDictionary; @@ -180,6 +181,7 @@ export class TerminalTaskSystem implements ITaskSystem { ) { this.activeTasks = Object.create(null); + this.busyTasks = Object.create(null); this.terminals = Object.create(null); this.idleTaskTerminals = new LinkedMap(); this.sameTaskTerminals = Object.create(null); @@ -280,6 +282,10 @@ export class TerminalTaskSystem implements ITaskSystem { return Object.keys(this.activeTasks).map(key => this.activeTasks[key].task); } + public getBusyTasks(): Task[] { + return Object.keys(this.busyTasks).map(key => this.busyTasks[key]); + } + public customExecutionComplete(task: Task, result: number): Promise { let activeTerminal = this.activeTasks[task.getMapKey()]; if (!activeTerminal) { @@ -533,12 +539,17 @@ export class TerminalTaskSystem implements ITaskSystem { } const toDispose = new DisposableStore(); let eventCounter: number = 0; + const mapKey = task.getMapKey(); toDispose.add(watchingProblemMatcher.onDidStateChange((event) => { if (event.kind === ProblemCollectorEventKind.BackgroundProcessingBegins) { eventCounter++; + this.busyTasks[mapKey] = task; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task)); } else if (event.kind === ProblemCollectorEventKind.BackgroundProcessingEnds) { eventCounter--; + if (this.busyTasks[mapKey]) { + delete this.busyTasks[mapKey]; + } this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task)); if (eventCounter === 0) { if ((watchingProblemMatcher.numberOfMatches > 0) && watchingProblemMatcher.maxMarkerSeverity && @@ -597,6 +608,9 @@ export class TerminalTaskSystem implements ITaskSystem { onData.dispose(); onExit.dispose(); let key = task.getMapKey(); + if (this.busyTasks[mapKey]) { + delete this.busyTasks[mapKey]; + } delete this.activeTasks[key]; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Changed)); if (exitCode !== undefined) { @@ -656,6 +670,8 @@ export class TerminalTaskSystem implements ITaskSystem { // The process never got ready. Need to think how to handle this. }); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task, terminal.id)); + const mapKey = task.getMapKey(); + this.busyTasks[mapKey] = task; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task)); let problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers); let startStopProblemMatcher = new StartStopProblemCollector(problemMatchers, this.markerService, this.modelService, ProblemHandlingStrategy.Clean, this.fileService); @@ -709,6 +725,9 @@ export class TerminalTaskSystem implements ITaskSystem { } this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessEnded, task, exitCode)); + if (this.busyTasks[mapKey]) { + delete this.busyTasks[mapKey]; + } this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task)); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task)); resolve({ exitCode }); @@ -1028,7 +1047,11 @@ export class TerminalTaskSystem implements ITaskSystem { // This can happen if the terminal wasn't shutdown with an "immediate" flag and is expected. // For correct terminal re-use, the task needs to be deleted immediately. // Note that this shouldn't be a problem anymore since user initiated terminal kills are now immediate. - delete this.activeTasks[task.getMapKey()]; + const mapKey = task.getMapKey(); + delete this.activeTasks[mapKey]; + if (this.busyTasks[mapKey]) { + delete this.busyTasks[mapKey]; + } } }); this.terminals[terminalKey] = { terminal: result, lastTask: taskKey, group }; diff --git a/src/vs/workbench/contrib/tasks/common/taskService.ts b/src/vs/workbench/contrib/tasks/common/taskService.ts index a8005416329..e2811234e63 100644 --- a/src/vs/workbench/contrib/tasks/common/taskService.ts +++ b/src/vs/workbench/contrib/tasks/common/taskService.ts @@ -62,6 +62,7 @@ export interface ITaskService { inTerminal(): boolean; isActive(): Promise; getActiveTasks(): Promise; + getBusyTasks(): Promise; restart(task: Task): void; terminate(task: Task): Promise; terminateAll(): Promise; diff --git a/src/vs/workbench/contrib/tasks/common/taskSystem.ts b/src/vs/workbench/contrib/tasks/common/taskSystem.ts index c844be5ec26..9c9654adbf6 100644 --- a/src/vs/workbench/contrib/tasks/common/taskSystem.ts +++ b/src/vs/workbench/contrib/tasks/common/taskSystem.ts @@ -133,6 +133,7 @@ export interface ITaskSystem { isActive(): Promise; isActiveSync(): boolean; getActiveTasks(): Task[]; + getBusyTasks(): Task[]; canAutoTerminate(): boolean; terminate(task: Task): Promise; terminateAll(): Promise; diff --git a/src/vs/workbench/contrib/tasks/node/processTaskSystem.ts b/src/vs/workbench/contrib/tasks/node/processTaskSystem.ts index 8110db9d80c..ba3adbd5a48 100644 --- a/src/vs/workbench/contrib/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/node/processTaskSystem.ts @@ -90,6 +90,10 @@ export class ProcessTaskSystem implements ITaskSystem { return result; } + public getBusyTasks(): Task[] { + return this.getActiveTasks(); + } + public run(task: Task): ITaskExecuteResult { if (this.activeTask) { return { kind: TaskExecuteKind.Active, task, active: { same: this.activeTask._id === task._id, background: this.activeTask.configurationProperties.isBackground! }, promise: this.activeTaskPromise! }; From 1cd8dce12c570e9b869a842dff8bedfbff223002 Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Fri, 11 Oct 2019 11:56:05 +0200 Subject: [PATCH 410/435] Create pull_request_template.md --- .github/pull_request_template.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000..44e6d90312c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,9 @@ + + +This PR fixes # From d952f6bfc1083ce5a913e07dfc4b8895ef0589ef Mon Sep 17 00:00:00 2001 From: yamachu Date: Fri, 11 Oct 2019 19:07:31 +0900 Subject: [PATCH 411/435] Fixed the problem of overwriting many characters in suggestion --- src/vs/editor/contrib/suggest/suggestController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index f8ab47834a4..b8cb308422c 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -265,7 +265,7 @@ export class SuggestController implements IEditorContribution { let overwriteBefore = position.column - suggestion.range.startColumn; let overwriteAfter = suggestion.range.endColumn - position.column; - let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(position) : 0; + let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(editorPosition) : 0; let word: IWordAtPosition | null; if (!keepSuffix) { // don't overwrite anything right of the cursor @@ -273,7 +273,7 @@ export class SuggestController implements IEditorContribution { } else if (overwriteAfter === 0 && (word = model.getWordAtPosition(position))) { // compute fallback overwrite length - overwriteAfter = word.endColumn - position.column; + overwriteAfter = word.endColumn - editorPosition.column; } SnippetController2.get(this._editor).insert(insertText, { From cc6d174f7c7a7d1735b9623cfedb9515f87f9432 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 12:35:46 +0200 Subject: [PATCH 412/435] Add task end fire so that executions are cleaned up Fixes #81777 --- src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index bf87275c1cc..a5e45fe11e9 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -488,6 +488,8 @@ export class TerminalTaskSystem implements ITaskSystem { this.currentTask.resolvedVariables = resolvedVariables; return this.executeInTerminal(task, trigger, new VariableResolver(workspaceFolder, systemInfo, resolvedVariables.variables, this.configurationResolverService), workspaceFolder); } else { + // Allows the taskExecutions array to be updated in the extension host + this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task)); return Promise.resolve({ exitCode: 0 }); } }, reason => { From 6251b1c226b86283317b9591213cbdf541269a0d Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Fri, 11 Oct 2019 14:21:06 +0200 Subject: [PATCH 413/435] Update pull_request_template.md --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 44e6d90312c..276121a227b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,7 +2,7 @@ * Read our Pull Request guidelines: https://github.com/Microsoft/vscode/wiki/How-to-Contribute#pull-requests. * Associate an issue with the Pull Request. -* Ensure that the Code is up-to-date with the `master` branch. +* Ensure that the code is up-to-date with the `master` branch. * Include a description of the proposed changes and how to test them. --> From dc4b1c231ce880319da45fc4bac944a6327ec358 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 14:43:23 +0200 Subject: [PATCH 414/435] Rename CustomExecution2 to CustomExecution Part of #80375 --- .../workspace.tasks.test.ts | 4 +- src/vs/vscode.d.ts | 2 +- src/vs/vscode.proposed.d.ts | 6 +- .../workbench/api/browser/mainThreadTask.ts | 26 ++++----- .../workbench/api/common/extHost.api.impl.ts | 2 +- src/vs/workbench/api/common/extHostTask.ts | 58 +++++++++---------- src/vs/workbench/api/common/extHostTypes.ts | 16 ++--- src/vs/workbench/api/common/shared/tasks.ts | 6 +- src/vs/workbench/api/node/extHostTask.ts | 10 ++-- .../tasks/browser/terminalTaskSystem.ts | 8 +-- .../workbench/contrib/tasks/common/tasks.ts | 10 ++-- 11 files changed, 74 insertions(+), 74 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts index 7f21223b344..525b5a9318c 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts @@ -10,7 +10,7 @@ suite('workspace-namespace', () => { suite('Tasks', () => { - test('CustomExecution2 task should start and shutdown successfully', (done) => { + test('CustomExecution task should start and shutdown successfully', (done) => { interface CustomTestingTaskDefinition extends vscode.TaskDefinition { /** * One of the task properties. This can be used to customize the task in the tasks.json @@ -35,7 +35,7 @@ suite('workspace-namespace', () => { customProp1: 'testing task one' }; const writeEmitter = new vscode.EventEmitter(); - const execution = new vscode.CustomExecution2((): Thenable => { + const execution = new vscode.CustomExecution((): Thenable => { const pty: vscode.Pseudoterminal = { onDidWrite: writeEmitter.event, open: () => { diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index dcf606c6a46..b60d66b6b4f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -7298,7 +7298,7 @@ declare module 'vscode' { * A number can be used to provide an exit code for the terminal. Exit codes must be * positive and a non-zero exit codes signals failure which shows a notification for a * regular terminal and allows dependent tasks to proceed when used with the - * `CustomExecution2` API. + * `CustomExecution` API. * * **Example:** Exit the terminal when "y" is pressed, otherwise show a notification. * ```typescript diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 183148f6570..b4ab5f9a664 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -942,7 +942,7 @@ declare module 'vscode' { /** * Class used to execute an extension callback as a task. */ - export class CustomExecution2 { + export class CustomExecution { /** * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until @@ -971,12 +971,12 @@ declare module 'vscode' { * or '$eslint'. Problem matchers can be contributed by an extension using * the `problemMatchers` extension point. */ - constructor(taskDefinition: TaskDefinition, scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]); + constructor(taskDefinition: TaskDefinition, scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution, problemMatchers?: string | string[]); /** * The task's execution engine */ - execution2?: ProcessExecution | ShellExecution | CustomExecution2; + execution2?: ProcessExecution | ShellExecution | CustomExecution; } //#endregion diff --git a/src/vs/workbench/api/browser/mainThreadTask.ts b/src/vs/workbench/api/browser/mainThreadTask.ts index e904b50d182..e8b10b69e5d 100644 --- a/src/vs/workbench/api/browser/mainThreadTask.ts +++ b/src/vs/workbench/api/browser/mainThreadTask.ts @@ -29,7 +29,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; import { TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO, - ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecution2DTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO, + ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecutionDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO, RunOptionsDTO } from 'vs/workbench/api/common/shared/tasks'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; @@ -131,7 +131,7 @@ namespace ProcessExecutionOptionsDTO { } namespace ProcessExecutionDTO { - export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ProcessExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is ProcessExecutionDTO { const candidate = value as ProcessExecutionDTO; return candidate && !!candidate.process; } @@ -199,7 +199,7 @@ namespace ShellExecutionOptionsDTO { } namespace ShellExecutionDTO { - export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ShellExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is ShellExecutionDTO { const candidate = value as ShellExecutionDTO; return candidate && (!!candidate.commandLine || !!candidate.command); } @@ -230,21 +230,21 @@ namespace ShellExecutionDTO { } } -namespace CustomExecution2DTO { - export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is CustomExecution2DTO { - const candidate = value as CustomExecution2DTO; - return candidate && candidate.customExecution === 'customExecution2'; +namespace CustomExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is CustomExecutionDTO { + const candidate = value as CustomExecutionDTO; + return candidate && candidate.customExecution === 'customExecution'; } - export function from(value: CommandConfiguration): CustomExecution2DTO { + export function from(value: CommandConfiguration): CustomExecutionDTO { return { - customExecution: 'customExecution2' + customExecution: 'customExecution' }; } - export function to(value: CustomExecution2DTO): CommandConfiguration { + export function to(value: CustomExecutionDTO): CommandConfiguration { return { - runtime: RuntimeType.CustomExecution2, + runtime: RuntimeType.CustomExecution, presentation: undefined }; } @@ -351,8 +351,8 @@ namespace TaskDTO { command = ShellExecutionDTO.to(task.execution); } else if (ProcessExecutionDTO.is(task.execution)) { command = ProcessExecutionDTO.to(task.execution); - } else if (CustomExecution2DTO.is(task.execution)) { - command = CustomExecution2DTO.to(task.execution); + } else if (CustomExecutionDTO.is(task.execution)) { + command = CustomExecutionDTO.to(task.execution); } } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b01c507517a..98f5405717a 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -847,7 +847,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I EndOfLine: extHostTypes.EndOfLine, EventEmitter: Emitter, ExtensionKind: extHostTypes.ExtensionKind, - CustomExecution2: extHostTypes.CustomExecution2, + CustomExecution: extHostTypes.CustomExecution, FileChangeType: extHostTypes.FileChangeType, FileSystemError: extHostTypes.FileSystemError, FileType: files.FileType, diff --git a/src/vs/workbench/api/common/extHostTask.ts b/src/vs/workbench/api/common/extHostTask.ts index 7cd590692fd..1fbe711b32b 100644 --- a/src/vs/workbench/api/common/extHostTask.ts +++ b/src/vs/workbench/api/common/extHostTask.ts @@ -88,7 +88,7 @@ export namespace ProcessExecutionOptionsDTO { } export namespace ProcessExecutionDTO { - export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecution2DTO | undefined): value is tasks.ProcessExecutionDTO { + export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecutionDTO | undefined): value is tasks.ProcessExecutionDTO { if (value) { const candidate = value as tasks.ProcessExecutionDTO; return candidate && !!candidate.process; @@ -133,7 +133,7 @@ export namespace ShellExecutionOptionsDTO { } export namespace ShellExecutionDTO { - export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecution2DTO | undefined): value is tasks.ShellExecutionDTO { + export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecutionDTO | undefined): value is tasks.ShellExecutionDTO { if (value) { const candidate = value as tasks.ShellExecutionDTO; return candidate && (!!candidate.commandLine || !!candidate.command); @@ -170,19 +170,19 @@ export namespace ShellExecutionDTO { } } -export namespace CustomExecution2DTO { - export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecution2DTO | undefined): value is tasks.CustomExecution2DTO { +export namespace CustomExecutionDTO { + export function is(value: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecutionDTO | undefined): value is tasks.CustomExecutionDTO { if (value) { - let candidate = value as tasks.CustomExecution2DTO; - return candidate && candidate.customExecution === 'customExecution2'; + let candidate = value as tasks.CustomExecutionDTO; + return candidate && candidate.customExecution === 'customExecution'; } else { return false; } } - export function from(value: vscode.CustomExecution2): tasks.CustomExecution2DTO { + export function from(value: vscode.CustomExecution): tasks.CustomExecutionDTO { return { - customExecution: 'customExecution2' + customExecution: 'customExecution' }; } } @@ -220,13 +220,13 @@ export namespace TaskDTO { if (value === undefined || value === null) { return undefined; } - let execution: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecution2DTO | undefined; + let execution: tasks.ShellExecutionDTO | tasks.ProcessExecutionDTO | tasks.CustomExecutionDTO | undefined; if (value.execution instanceof types.ProcessExecution) { execution = ProcessExecutionDTO.from(value.execution); } else if (value.execution instanceof types.ShellExecution) { execution = ShellExecutionDTO.from(value.execution); - } else if ((value).execution2 && (value).execution2 instanceof types.CustomExecution2) { - execution = CustomExecution2DTO.from((value).execution2); + } else if ((value).execution2 && (value).execution2 instanceof types.CustomExecution) { + execution = CustomExecutionDTO.from((value).execution2); } const definition: tasks.TaskDefinitionDTO | undefined = TaskDefinitionDTO.from(value.definition); @@ -373,9 +373,9 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { protected _handleCounter: number; protected _handlers: Map; protected _taskExecutions: Map; - protected _providedCustomExecutions2: Map; + protected _providedCustomExecutions2: Map; private _notProvidedCustomExecutions: Set; // Used for custom executions tasks that are created and run through executeTask. - protected _activeCustomExecutions2: Map; + protected _activeCustomExecutions2: Map; private _lastStartedTask: string | undefined; protected readonly _onDidExecuteTask: Emitter = new Emitter(); protected readonly _onDidTerminateTask: Emitter = new Emitter(); @@ -399,9 +399,9 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { this._handleCounter = 0; this._handlers = new Map(); this._taskExecutions = new Map(); - this._providedCustomExecutions2 = new Map(); + this._providedCustomExecutions2 = new Map(); this._notProvidedCustomExecutions = new Set(); - this._activeCustomExecutions2 = new Map(); + this._activeCustomExecutions2 = new Map(); } public registerTaskProvider(extension: IExtensionDescription, type: string, provider: vscode.TaskProvider): vscode.Disposable { @@ -454,15 +454,15 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { } public async $onDidStartTask(execution: tasks.TaskExecutionDTO, terminalId: number): Promise { - const execution2: types.CustomExecution2 | undefined = this._providedCustomExecutions2.get(execution.id); - if (execution2) { + const customExecution: types.CustomExecution | undefined = this._providedCustomExecutions2.get(execution.id); + if (customExecution) { if (this._activeCustomExecutions2.get(execution.id) !== undefined) { throw new Error('We should not be trying to start the same custom task executions twice.'); } // Clone the custom execution to keep the original untouched. This is important for multiple runs of the same task. - this._activeCustomExecutions2.set(execution.id, execution2); - this._terminalService.attachPtyToTerminal(terminalId, await execution2.callback()); + this._activeCustomExecutions2.set(execution.id, customExecution); + this._terminalService.attachPtyToTerminal(terminalId, await customExecution.callback()); } this._lastStartedTask = execution.id; @@ -573,8 +573,8 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { throw new Error('Unexpected: The resolved task definition must be the same object as the original task definition. The task definition cannot be changed.'); } - if (CustomExecution2DTO.is(resolvedTaskDTO.execution)) { - await this.addCustomExecution2(resolvedTaskDTO, resolvedTask, true); + if (CustomExecutionDTO.is(resolvedTaskDTO.execution)) { + await this.addCustomExecution(resolvedTaskDTO, resolvedTask, true); } return await this.resolveTaskInternal(resolvedTaskDTO); @@ -588,12 +588,12 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { return this._handleCounter++; } - protected async addCustomExecution2(taskDTO: tasks.TaskDTO, task: vscode.Task2, isProvided: boolean): Promise { + protected async addCustomExecution(taskDTO: tasks.TaskDTO, task: vscode.Task2, isProvided: boolean): Promise { const taskId = await this._proxy.$createTaskId(taskDTO); if (!isProvided && !this._providedCustomExecutions2.has(taskId)) { this._notProvidedCustomExecutions.add(taskId); } - this._providedCustomExecutions2.set(taskId, (task).execution2); + this._providedCustomExecutions2.set(taskId, (task).execution2); } protected async getTaskExecution(execution: tasks.TaskExecutionDTO | string, task?: vscode.Task): Promise { @@ -619,7 +619,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape { } private customExecutionComplete(execution: tasks.TaskExecutionDTO): void { - const extensionCallback2: vscode.CustomExecution2 | undefined = this._activeCustomExecutions2.get(execution.id); + const extensionCallback2: vscode.CustomExecution | undefined = this._activeCustomExecutions2.get(execution.id); if (extensionCallback2) { this._activeCustomExecutions2.delete(execution.id); } @@ -674,8 +674,8 @@ export class WorkerExtHostTask extends ExtHostTaskBase { // If this task is a custom execution, then we need to save it away // in the provided custom execution map that is cleaned up after the // task is executed. - if (CustomExecution2DTO.is(dto.execution)) { - await this.addCustomExecution2(dto, task, false); + if (CustomExecutionDTO.is(dto.execution)) { + await this.addCustomExecution(dto, task, false); } else { throw new Error('Not implemented'); } @@ -692,12 +692,12 @@ export class WorkerExtHostTask extends ExtHostTaskBase { } const taskDTO: tasks.TaskDTO | undefined = TaskDTO.from(task, handler.extension); - if (taskDTO && CustomExecution2DTO.is(taskDTO.execution)) { + if (taskDTO && CustomExecutionDTO.is(taskDTO.execution)) { taskDTOs.push(taskDTO); // The ID is calculated on the main thread task side, so, let's call into it here. // We need the task id's pre-computed for custom task executions because when OnDidStartTask // is invoked, we have to be able to map it back to our data. - taskIdPromises.push(this.addCustomExecution2(taskDTO, task, true)); + taskIdPromises.push(this.addCustomExecution(taskDTO, task, true)); } else { console.warn('Only custom execution tasks supported.'); } @@ -710,7 +710,7 @@ export class WorkerExtHostTask extends ExtHostTaskBase { } protected async resolveTaskInternal(resolvedTaskDTO: tasks.TaskDTO): Promise { - if (CustomExecution2DTO.is(resolvedTaskDTO.execution)) { + if (CustomExecutionDTO.is(resolvedTaskDTO.execution)) { return resolvedTaskDTO; } else { console.warn('Only custom execution tasks supported.'); diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index a71f8c6ea52..a5644289cf7 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1776,7 +1776,7 @@ export enum TaskScope { Workspace = 2 } -export class CustomExecution2 implements vscode.CustomExecution2 { +export class CustomExecution implements vscode.CustomExecution { private _callback: () => Thenable; constructor(callback: () => Thenable) { this._callback = callback; @@ -1807,7 +1807,7 @@ export class Task implements vscode.Task2 { private _definition: vscode.TaskDefinition; private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder | undefined; private _name: string; - private _execution: ProcessExecution | ShellExecution | CustomExecution2 | undefined; + private _execution: ProcessExecution | ShellExecution | CustomExecution | undefined; private _problemMatchers: string[]; private _hasDefinedMatchers: boolean; private _isBackground: boolean; @@ -1816,8 +1816,8 @@ export class Task implements vscode.Task2 { private _presentationOptions: vscode.TaskPresentationOptions; private _runOptions: vscode.RunOptions; - constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]); - constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]); + constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution, problemMatchers?: string | string[]); + constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution, problemMatchers?: string | string[]); constructor(definition: vscode.TaskDefinition, arg2: string | (vscode.TaskScope.Global | vscode.TaskScope.Workspace) | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) { this._definition = this.definition = definition; let problemMatchers: string | string[]; @@ -1882,7 +1882,7 @@ export class Task implements vscode.Task2 { type: Task.ShellType, id: this._execution.computeId() }; - } else if (this._execution instanceof CustomExecution2) { + } else if (this._execution instanceof CustomExecution) { this._definition = { type: Task.ExtensionCallbackType, id: this._execution.computeId() @@ -1929,18 +1929,18 @@ export class Task implements vscode.Task2 { } get execution(): ProcessExecution | ShellExecution | undefined { - return (this._execution instanceof CustomExecution2) ? undefined : this._execution; + return (this._execution instanceof CustomExecution) ? undefined : this._execution; } set execution(value: ProcessExecution | ShellExecution | undefined) { this.execution2 = value; } - get execution2(): ProcessExecution | ShellExecution | CustomExecution2 | undefined { + get execution2(): ProcessExecution | ShellExecution | CustomExecution | undefined { return this._execution; } - set execution2(value: ProcessExecution | ShellExecution | CustomExecution2 | undefined) { + set execution2(value: ProcessExecution | ShellExecution | CustomExecution | undefined) { if (value === null) { value = undefined; } diff --git a/src/vs/workbench/api/common/shared/tasks.ts b/src/vs/workbench/api/common/shared/tasks.ts index b8fab0b5a02..e31f4e6b807 100644 --- a/src/vs/workbench/api/common/shared/tasks.ts +++ b/src/vs/workbench/api/common/shared/tasks.ts @@ -66,8 +66,8 @@ export interface ShellExecutionDTO { options?: ShellExecutionOptionsDTO; } -export interface CustomExecution2DTO { - customExecution: 'customExecution2'; +export interface CustomExecutionDTO { + customExecution: 'customExecution'; } export interface TaskSourceDTO { @@ -84,7 +84,7 @@ export interface TaskHandleDTO { export interface TaskDTO { _id: string; name?: string; - execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecution2DTO | undefined; + execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecutionDTO | undefined; definition: TaskDefinitionDTO; isBackground?: boolean; source: TaskSourceDTO; diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 71d8b818b72..5c167085086 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -19,7 +19,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; -import { ExtHostTaskBase, TaskHandleDTO, TaskDTO, CustomExecution2DTO, HandlerData } from 'vs/workbench/api/common/extHostTask'; +import { ExtHostTaskBase, TaskHandleDTO, TaskDTO, CustomExecutionDTO, HandlerData } from 'vs/workbench/api/common/extHostTask'; import { Schemas } from 'vs/base/common/network'; export class ExtHostTask extends ExtHostTaskBase { @@ -56,8 +56,8 @@ export class ExtHostTask extends ExtHostTaskBase { // If this task is a custom execution, then we need to save it away // in the provided custom execution map that is cleaned up after the // task is executed. - if (CustomExecution2DTO.is(dto.execution)) { - await this.addCustomExecution2(dto, task, false); + if (CustomExecutionDTO.is(dto.execution)) { + await this.addCustomExecution(dto, task, false); } return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task)); @@ -76,11 +76,11 @@ export class ExtHostTask extends ExtHostTaskBase { if (taskDTO) { taskDTOs.push(taskDTO); - if (CustomExecution2DTO.is(taskDTO.execution)) { + if (CustomExecutionDTO.is(taskDTO.execution)) { // The ID is calculated on the main thread task side, so, let's call into it here. // We need the task id's pre-computed for custom task executions because when OnDidStartTask // is invoked, we have to be able to map it back to our data. - taskIdPromises.push(this.addCustomExecution2(taskDTO, task, true)); + taskIdPromises.push(this.addCustomExecution(taskDTO, task, true)); } } } diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index a5e45fe11e9..d9a72726f47 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -483,7 +483,7 @@ export class TerminalTaskSystem implements ITaskSystem { const resolvedVariables = this.resolveVariablesFromSet(systemInfo, workspaceFolder, task, variables); return resolvedVariables.then((resolvedVariables) => { - const isCustomExecution = (task.command.runtime === RuntimeType.CustomExecution2); + const isCustomExecution = (task.command.runtime === RuntimeType.CustomExecution); if (resolvedVariables && (task.command !== undefined) && task.command.runtime && (isCustomExecution || (task.command.name !== undefined))) { this.currentTask.resolvedVariables = resolvedVariables; return this.executeInTerminal(task, trigger, new VariableResolver(workspaceFolder, systemInfo, resolvedVariables.variables, this.configurationResolverService), workspaceFolder); @@ -882,7 +882,7 @@ export class TerminalTaskSystem implements ITaskSystem { } } } else { - let commandExecutable = (task.command.runtime !== RuntimeType.CustomExecution2) ? CommandString.value(command) : undefined; + let commandExecutable = (task.command.runtime !== RuntimeType.CustomExecution) ? CommandString.value(command) : undefined; let executable = !isShellCommand ? this.resolveVariable(variableResolver, '${' + TerminalTaskSystem.ProcessVarName + '}') : commandExecutable; @@ -953,7 +953,7 @@ export class TerminalTaskSystem implements ITaskSystem { let args: CommandString[] | undefined; let launchConfigs: IShellLaunchConfig | undefined; - if (task.command.runtime === RuntimeType.CustomExecution2) { + if (task.command.runtime === RuntimeType.CustomExecution) { this.currentTask.shellLaunchConfig = launchConfigs = { isExtensionTerminal: true, waitOnExit, @@ -1179,7 +1179,7 @@ export class TerminalTaskSystem implements ITaskSystem { private collectCommandVariables(variables: Set, command: CommandConfiguration, task: CustomTask | ContributedTask): void { // The custom execution should have everything it needs already as it provided // the callback. - if (command.runtime === RuntimeType.CustomExecution2) { + if (command.runtime === RuntimeType.CustomExecution) { return; } diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 760c3f67664..66a00708221 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -274,7 +274,7 @@ export namespace PresentationOptions { export enum RuntimeType { Shell = 1, Process = 2, - CustomExecution2 = 3 + CustomExecution = 3 } export namespace RuntimeType { @@ -284,8 +284,8 @@ export namespace RuntimeType { return RuntimeType.Shell; case 'process': return RuntimeType.Process; - case 'customExecution2': - return RuntimeType.CustomExecution2; + case 'customExecution': + return RuntimeType.CustomExecution; default: return RuntimeType.Process; } @@ -680,8 +680,8 @@ export class CustomTask extends CommonTask { type = 'process'; break; - case RuntimeType.CustomExecution2: - type = 'customExecution2'; + case RuntimeType.CustomExecution: + type = 'customExecution'; break; case undefined: From 13584cceaf17f716c99a7c09bedf23548cd73d89 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 11 Oct 2019 15:38:37 +0200 Subject: [PATCH 415/435] :lipstick: --- src/vs/base/browser/ui/tree/objectTree.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index be6082a4661..fa77e74cd8a 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -59,10 +59,6 @@ interface ICompressedTreeNodeProvider { getCompressedTreeNode(element: T): ITreeNode, TFilterData>; } -export interface ICompressibleObjectTreeOptions extends IObjectTreeOptions { - readonly elementMapper?: ElementMapper; -} - export interface ICompressibleTreeRenderer extends ITreeRenderer { renderCompressedElements(node: ITreeNode, TFilterData>, index: number, templateData: TTemplateData, height: number | undefined): void; disposeCompressedElements?(node: ITreeNode, TFilterData>, index: number, templateData: TTemplateData, height: number | undefined): void; @@ -136,6 +132,7 @@ export interface ICompressibleKeyboardNavigationLabelProvider extends IKeyboa } export interface ICompressibleObjectTreeOptions extends IObjectTreeOptions { + readonly elementMapper?: ElementMapper; readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider; } From a7f3a3732ecbf22c8869dcb2f4aaefde8901a522 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 11 Oct 2019 15:40:07 +0200 Subject: [PATCH 416/435] more :lipstick: --- src/vs/base/browser/ui/tree/objectTree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index fa77e74cd8a..b168e7e14ce 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -14,7 +14,7 @@ import { CompressibleObjectTreeModel, ElementMapper, ICompressedTreeNode, ICompr import { memoize } from 'vs/base/common/decorators'; export interface IObjectTreeOptions extends IAbstractTreeOptions { - sorter?: ITreeSorter; + readonly sorter?: ITreeSorter; } export class ObjectTree, TFilterData = void> extends AbstractTree { From 5a63e286a790f01367627a685a3b24487a6f978e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 11 Oct 2019 15:40:17 +0200 Subject: [PATCH 417/435] fixes #82346 --- src/vs/workbench/contrib/scm/browser/repositoryPanel.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts index 98590275af1..ab56475c074 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPanel.ts @@ -382,8 +382,7 @@ function asTreeElement(node: INode, incompressi return { element: node, children: Iterator.map(node.children, node => asTreeElement(node, false)), - incompressible, - collapsed: false + incompressible }; } From cc100aa6645ca342c228b125332a15ecf7ea10da Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 16:01:30 +0200 Subject: [PATCH 418/435] Add ability to have OS specific task problem matchers Fixes #59023 --- .../tasks/browser/terminalTaskSystem.ts | 2 +- .../contrib/tasks/common/jsonSchemaCommon.ts | 50 ++++++++-- .../contrib/tasks/common/taskConfiguration.ts | 96 ++++--------------- 3 files changed, 61 insertions(+), 87 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index d9a72726f47..62f8180824b 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -535,7 +535,7 @@ export class TerminalTaskSystem implements ITaskSystem { if (task.configurationProperties.isBackground) { const problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers); let watchingProblemMatcher = new WatchingProblemCollector(problemMatchers, this.markerService, this.modelService, this.fileService); - if (!watchingProblemMatcher.isWatching()) { + if ((problemMatchers.length > 0) && !watchingProblemMatcher.isWatching()) { this.appendOutput(nls.localize('TerminalTaskSystem.nonWatchingMatcher', 'Task {0} is a background task but uses a problem matcher without a background pattern', task._label)); this.showOutput(); } diff --git a/src/vs/workbench/contrib/tasks/common/jsonSchemaCommon.ts b/src/vs/workbench/contrib/tasks/common/jsonSchemaCommon.ts index 89f5ef65397..0d868b77c1a 100644 --- a/src/vs/workbench/contrib/tasks/common/jsonSchemaCommon.ts +++ b/src/vs/workbench/contrib/tasks/common/jsonSchemaCommon.ts @@ -115,16 +115,52 @@ const schema: IJSONSchema = { $ref: '#/definitions/options' }, windows: { - $ref: '#/definitions/commandConfiguration', - description: nls.localize('JsonSchema.tasks.windows', 'Windows specific command configuration') + anyOf: [ + { + $ref: '#/definitions/commandConfiguration', + description: nls.localize('JsonSchema.tasks.windows', 'Windows specific command configuration'), + }, + { + properties: { + problemMatcher: { + $ref: '#/definitions/problemMatcherType', + description: nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.') + } + } + } + ] }, osx: { - $ref: '#/definitions/commandConfiguration', - description: nls.localize('JsonSchema.tasks.mac', 'Mac specific command configuration') + anyOf: [ + { + $ref: '#/definitions/commandConfiguration', + description: nls.localize('JsonSchema.tasks.mac', 'Mac specific command configuration') + }, + { + properties: { + problemMatcher: { + $ref: '#/definitions/problemMatcherType', + description: nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.') + } + } + } + ] }, linux: { - $ref: '#/definitions/commandConfiguration', - description: nls.localize('JsonSchema.tasks.linux', 'Linux specific command configuration') + anyOf: [ + { + $ref: '#/definitions/commandConfiguration', + description: nls.localize('JsonSchema.tasks.linux', 'Linux specific command configuration') + }, + { + properties: { + problemMatcher: { + $ref: '#/definitions/problemMatcherType', + description: nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.') + } + } + } + ] }, suppressTaskName: { type: 'boolean', @@ -241,4 +277,4 @@ const schema: IJSONSchema = { } }; -export default schema; \ No newline at end of file +export default schema; diff --git a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts index dcefd54e051..fa7fbeb3133 100644 --- a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts +++ b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts @@ -1115,6 +1115,20 @@ namespace ProblemMatcherConverter { return result; } + export function fromWithOsConfig(this: void, external: ConfigurationProperties & { [key: string]: any; }, context: ParseContext): ProblemMatcher[] | undefined { + let result: ProblemMatcher[] | undefined = undefined; + if (external.windows && external.windows.problemMatcher && context.platform === Platform.Windows) { + result = from(external.windows.problemMatcher, context); + } else if (external.osx && external.osx.problemMatcher && context.platform === Platform.Mac) { + result = from(external.osx.problemMatcher, context); + } else if (external.linux && external.linux.problemMatcher && context.platform === Platform.Linux) { + result = from(external.linux.problemMatcher, context); + } else if (external.problemMatcher) { + result = from(external.problemMatcher, context); + } + return result; + } + export function from(this: void, config: ProblemMatcherConfig.ProblemMatcherType | undefined, context: ParseContext): ProblemMatcher[] { let result: ProblemMatcher[] = []; if (config === undefined) { @@ -1305,8 +1319,9 @@ namespace ConfigurationProperties { if (includeCommandOptions && (external.options !== undefined)) { result.options = CommandOptions.from(external.options, context); } - if (external.problemMatcher) { - result.problemMatchers = ProblemMatcherConverter.from(external.problemMatcher, context); + const configProblemMatcher = ProblemMatcherConverter.fromWithOsConfig(external, context); + if (configProblemMatcher !== undefined) { + result.problemMatchers = configProblemMatcher; } return isEmpty(result) ? undefined : result; } @@ -2047,80 +2062,3 @@ export function createCustomTask(contributedTask: Tasks.ContributedTask, configu return CustomTask.createCustomTask(contributedTask, configuredProps); } -/* -class VersionConverter { - constructor(private problemReporter: IProblemReporter) { - } - - public convert(fromConfig: ExternalTaskRunnerConfiguration): ExternalTaskRunnerConfiguration { - let result: ExternalTaskRunnerConfiguration; - result.version = '2.0.0'; - if (Array.isArray(fromConfig.tasks)) { - - } else { - result.tasks = []; - } - - - return result; - } - - private convertGlobalTask(fromConfig: ExternalTaskRunnerConfiguration): TaskDescription { - let command: string = this.getGlobalCommand(fromConfig); - if (!command) { - this.problemReporter.error(nls.localize('Converter.noGlobalName', 'No global command specified. Can\'t convert to 2.0.0 version.')); - return undefined; - } - let result: TaskDescription = { - taskName: command - }; - if (fromConfig.isShellCommand) { - result.type = 'shell'; - } else { - result.type = 'process'; - result.args = fromConfig.args; - } - if (fromConfig.) - - return result; - } - - private getGlobalCommand(fromConfig: ExternalTaskRunnerConfiguration): string { - if (fromConfig.command) { - return fromConfig.command; - } else if (fromConfig.windows && fromConfig.windows.command) { - return fromConfig.windows.command; - } else if (fromConfig.osx && fromConfig.osx.command) { - return fromConfig.osx.command; - } else if (fromConfig.linux && fromConfig.linux.command) { - return fromConfig.linux.command; - } else { - return undefined; - } - } - - private createCommandLine(command: string, args: string[], isWindows: boolean): string { - let result: string[]; - let commandHasSpace = false; - let argHasSpace = false; - if (TaskDescription.hasUnescapedSpaces(command)) { - result.push(`"${command}"`); - commandHasSpace = true; - } else { - result.push(command); - } - if (args) { - for (let arg of args) { - if (TaskDescription.hasUnescapedSpaces(arg)) { - result.push(`"${arg}"`); - argHasSpace= true; - } else { - result.push(arg); - } - } - } - return result.join(' '); - } - -} -*/ From 4425701a16d70f54a44eefca0195f0f6a3db9086 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 16:15:51 +0200 Subject: [PATCH 419/435] Add tasks setting to turn off all task auto detection Fixes #63841 --- .../workbench/contrib/tasks/browser/abstractTaskService.ts | 7 ++++++- .../workbench/contrib/tasks/browser/task.contribution.ts | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index c5dd5a080c9..d2756609d42 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -680,6 +680,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer }); } + private isProvideTasksEnabled(): boolean { + const settingValue = this.configurationService.getValue('task.autoDetect'); + return settingValue === true; + } + private shouldAttachProblemMatcher(task: Task): boolean { const settingValue = this.configurationService.getValue('task.problemMatchers.neverPrompt'); if (settingValue === true) { @@ -1259,7 +1264,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } } }; - if (this.schemaVersion === JsonSchemaVersion.V2_0_0 && this._providers.size > 0) { + if (this.isProvideTasksEnabled() && (this.schemaVersion === JsonSchemaVersion.V2_0_0) && (this._providers.size > 0)) { for (const [handle, provider] of this._providers) { if ((type === undefined) || (type === this._providerTypes.get(handle))) { counter++; diff --git a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts index c71ef786480..96136e89d0b 100644 --- a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts +++ b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts @@ -330,6 +330,11 @@ configurationRegistry.registerConfiguration({ } ], default: false + }, + 'task.autoDetect': { + markdownDescription: nls.localize('task.autoDetect', "Controls enablement of `provideTasks` for all task provider extension. If the Tasks: Run Task command is slow, disabling auto detect for task providers may help. Individual extensions my provide settings to disabled auto detection."), + type: 'boolean', + default: true } } }); From 2d87c95e53471539a1fab25a5367bb3eeffc9456 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Oct 2019 17:01:02 +0200 Subject: [PATCH 420/435] Don't show task quick pick for 'show' command when only one task Fixes #47505 --- .../tasks/browser/abstractTaskService.ts | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index d2756609d42..70a8b49af1a 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -372,8 +372,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer this.runConfigureDefaultTestTask(); }); - CommandsRegistry.registerCommand('workbench.action.tasks.showTasks', () => { - this.runShowTasks(); + CommandsRegistry.registerCommand('workbench.action.tasks.showTasks', async () => { + return this.runShowTasks(); }); CommandsRegistry.registerCommand('workbench.action.tasks.toggleProblems', () => { @@ -2493,23 +2493,28 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer } } - public runShowTasks(): void { + public async runShowTasks(): Promise { if (!this.canRunCommand()) { return; } - this.showQuickPick(this.getActiveTasks(), - nls.localize('TaskService.pickShowTask', 'Select the task to show its output'), - { - label: nls.localize('TaskService.noTaskIsRunning', 'No task is running'), - task: null - }, - false, true - ).then((entry) => { - let task: Task | undefined | null = entry ? entry.task : undefined; - if (task === undefined || task === null) { - return; - } - this._taskSystem!.revealTask(task); - }); + const activeTasks: Task[] = await this.getActiveTasks(); + if (activeTasks.length === 1) { + this._taskSystem!.revealTask(activeTasks[0]); + } else { + this.showQuickPick(this.getActiveTasks(), + nls.localize('TaskService.pickShowTask', 'Select the task to show its output'), + { + label: nls.localize('TaskService.noTaskIsRunning', 'No task is running'), + task: null + }, + false, true + ).then((entry) => { + let task: Task | undefined | null = entry ? entry.task : undefined; + if (task === undefined || task === null) { + return; + } + this._taskSystem!.revealTask(task); + }); + } } } From f26a2e84d16da48f79d68e1021021675c31b18d1 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Oct 2019 17:03:37 +0200 Subject: [PATCH 421/435] Fixes #65281: Treat the presence of \w as an indicator of a multiline regex search string --- src/vs/editor/common/model/textModelSearch.ts | 2 +- .../test/common/model/textModelSearch.test.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index f350079ee69..4622af82cbc 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -85,7 +85,7 @@ export function isMultilineRegexSource(searchString: string): boolean { } const nextChCode = searchString.charCodeAt(i); - if (nextChCode === CharCode.n || nextChCode === CharCode.r || nextChCode === CharCode.W) { + if (nextChCode === CharCode.n || nextChCode === CharCode.r || nextChCode === CharCode.W || nextChCode === CharCode.w) { return true; } } diff --git a/src/vs/editor/test/common/model/textModelSearch.test.ts b/src/vs/editor/test/common/model/textModelSearch.test.ts index aa90e1c0c3f..2a55d718b50 100644 --- a/src/vs/editor/test/common/model/textModelSearch.test.ts +++ b/src/vs/editor/test/common/model/textModelSearch.test.ts @@ -721,6 +721,20 @@ suite('TextModelSearch', () => { ); }); + test('issue #65281. \w should match line break.', () => { + assertFindMatches( + [ + 'this/is{', + 'a test', + '}', + ].join('\n'), + 'this/\\w*[^}]*', true, false, null, + [ + [1, 1, 3, 1] + ] + ); + }); + test('Simple find using unicode escape sequences', () => { assertFindMatches( regularText.join('\n'), From b880553e5e851167c23bdf6dece6e711dd37185a Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Oct 2019 08:06:18 -0700 Subject: [PATCH 422/435] Fix #82165 --- .../contrib/debug/browser/media/debug.contribution.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css b/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css index ca447ebd6d5..e8f8bad37cd 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/contrib/debug/browser/media/debug.contribution.css @@ -175,7 +175,7 @@ /* White color when element is selected and list is focused. White looks better on blue selection background. */ .monaco-workbench .monaco-list:focus .monaco-list-row.selected .expression .name, .monaco-workbench .monaco-list:focus .monaco-list-row.selected .expression .value { - color: white; + color: inherit; } .monaco-workbench .monaco-list-row .expression .name { From 3ee53ad714f64176f8db3d209896df4c1c0d01c1 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 11 Oct 2019 17:32:32 +0200 Subject: [PATCH 423/435] Fixes #69238: Avoid placing the hover above the page --- .../editor/browser/viewParts/contentWidgets/contentWidgets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 3a962f22ea2..eb49a439f9d 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -380,7 +380,7 @@ class Widget { belowLeft = absoluteBelowLeft; } - return { fitsAbove, aboveTop, aboveLeft, fitsBelow, belowTop, belowLeft }; + return { fitsAbove, aboveTop: Math.max(aboveTop, TOP_PADDING), aboveLeft, fitsBelow, belowTop, belowLeft }; } private _prepareRenderWidgetAtExactPositionOverflowing(topLeft: Coordinate): Coordinate { From debaebba50b36cf9f616a1a8c94ead8e9fa5935d Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Oct 2019 09:26:13 -0700 Subject: [PATCH 424/435] Update Chrome icons to render correctly on Windows --- .../ui/codiconLabel/codicon/codicon.css | 2 +- .../ui/codiconLabel/codicon/codicon.ttf | Bin 52860 -> 52836 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index 134bfe6f726..2ef19ad074b 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?815addc65cb9aac7efdb5ce4e69f9741") format("truetype"); + src: url("./codicon.ttf?419224353c2d776235f324ad51a4eac2") format("truetype"); } .codicon[class*='codicon-'] { diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf index 2040fb440c846396988498821760586caee729b0..3424ea95314bee90bcd3706c42c2c75932147cf5 100644 GIT binary patch delta 778 zcmew}hxy4I<_QiW-+6oHGcZVQVPIIwk&&91A~yM-(ZmoPmIvJ1c_y|f3+`cHVB#vs zFD~IyF`LN1aNxwm9R@O`hSJ{g{5D@1xS3xt0Kv^;vDq+sGYjKEvHA_{$Jnp1|KO10 z2;*49DaIMcIfe5Rml2l_*9LAeZX50b?nOL7Jd=2K@!Ijm@pkYo;=RJh!)L%}$9IL_ zh5wd-fPjs_B7q|U?*v5zT?EqvdjyXN{t(I%nj~~cm_b-ixIlP^h=xdj$O}Femn=}*zWXTWD*WpKh!!Ele!DPuO{D&t+o7ff7C8ce2`Tr!n0jWMk-U16qR=3;ih zoW*>a1&2kE#Vbn-%LL0N%L!HqR@bclS+`g}vdOZ!WouzO#rA|9i=CI<7JC`{7W-ZH zPaFgs0vzT!oN#1tv~yhL_{i~Jy;GjkE@wOEI_G^ZCN4!T`&1@lo@!@bU6l9RA~Q?hw%$j<==j$!oO!3zc5Vp*VM29DH22|Q#CeK y6jT;925B&|`{%{D?O&%I<2L)+zvmeL{5{KL3^Ze_z1=@=dnRLs&AT-ZE&%{rIrcpO delta 818 zcmaDdhxyMO<_QiWUym(3&%hwLg@IwILPlz0irB>09uq@!Se{v$jVN$}b5dGS5q z58!_$AS2)*uukBDz%M}s!2rP`!5M-Vgjj^igyspI6Xp@N60Q+GB4Q#EBl1PmN_3v+ zD=|5-ItNh zq;H|0rN2P`m4TFjo52-B9m5kw*NlaX+l-GH-!Ta==`mSga?e!5G{dyTbc>meS%BFY za{=>379tjP7T+vgEORXTEazC|SUs}lvYuf5&Zf-fnXQZM0^2Kg0(N0`2kbTMC)gje z|KK3w5aY1Q;ff=VqnG10$9GO#^-fhz$DF;KyPQwCIJnfgoN|qEZE#)WcFLW@UBx}f zJX^78ZAG!NXhcAP#nQxz; zh+mxF2ES+iI{r2O$Nb*}2n2)$^aZj6ss;WF@(P*&jD6<+|NjRtH#3_us4#3kC@H{S z&&0s+--r1Hvk3z?13v=;C!;tgqd6y|IwvE$x}u;W!Da%T&q0%D~CMz^JG!s3^z|G>PfmKOQ@#Li>L_j9-{4|Mr8K z43ix+)m=a;MUmACD=Lc`n<@$dNkOI!|Gey&jO_k-F>b2`GVOrWZpJ@<&oUX?|MO-l R+*A9{+n&jI^J2||O8_g82Lk{A From fb82295959a90497677597807bb320fe14ba2a22 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Oct 2019 10:12:01 -0700 Subject: [PATCH 425/435] Fix #74681 --- src/vs/workbench/contrib/scm/browser/media/scmViewlet.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css index 8bb02d5eaf1..c183da4ac40 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css +++ b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css @@ -41,10 +41,15 @@ } .scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar .action-item { + padding: 0 4px; overflow: hidden; text-overflow: ellipsis; } +.scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar .action-item:last-of-type { + padding-right: 0; +} + .scm-viewlet .scm-provider > .count { margin: 0 0.5em; } From f3d4a67c2dddf45cb1636f959ae47ce47ead60d2 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Oct 2019 10:50:09 -0700 Subject: [PATCH 426/435] Center scm text, badges, and icons --- .../contrib/scm/browser/media/scmViewlet.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css index c183da4ac40..3aeb9e527f7 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css +++ b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css @@ -44,12 +44,24 @@ padding: 0 4px; overflow: hidden; text-overflow: ellipsis; + display: flex; + align-items: center; +} + +.scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar .action-label .octicon { + font-size: 14px; } .scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar .action-item:last-of-type { padding-right: 0; } +.scm-viewlet .scm-provider > .name, +.scm-viewlet .scm-provider > .count { + display: flex; + align-items: center; +} + .scm-viewlet .scm-provider > .count { margin: 0 0.5em; } From 72f31853013ef80c7f604b70d3e0bda1e830a118 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Oct 2019 10:53:31 -0700 Subject: [PATCH 427/435] php - open executable settings if the validator fails Fixes https://github.com/microsoft/vscode/issues/8735 --- .../src/features/validationProvider.ts | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/extensions/php-language-features/src/features/validationProvider.ts b/extensions/php-language-features/src/features/validationProvider.ts index 6198974da88..c86a1f780ea 100644 --- a/extensions/php-language-features/src/features/validationProvider.ts +++ b/extensions/php-language-features/src/features/validationProvider.ts @@ -13,6 +13,13 @@ import { ThrottledDelayer } from './utils/async'; import * as nls from 'vscode-nls'; let localize = nls.loadMessageBundle(); +const enum Setting { + Run = 'php.validate.run', + CheckedExecutablePath = 'php.validate.checkedExecutablePath', + Enable = 'php.validate.enable', + ExecutablePath = 'php.validate.executablePath', +} + export class LineDecoder { private stringDecoder: NodeStringDecoder; private remaining: string | null; @@ -78,8 +85,6 @@ namespace RunTrigger { }; } -const CheckedExecutablePath = 'php.validate.checkedExecutablePath'; - export default class PHPValidationProvider { private static MatchExpression: RegExp = /(?:(?:Parse|Fatal) error): (.*)(?: in )(.*?)(?: on line )(\d+)/; @@ -129,11 +134,11 @@ export default class PHPValidationProvider { } private loadConfiguration(): void { - let section = vscode.workspace.getConfiguration('php'); + let section = vscode.workspace.getConfiguration(); let oldExecutable = this.executable; if (section) { - this.validationEnabled = section.get('validate.enable', true); - let inspect = section.inspect('validate.executablePath'); + this.validationEnabled = section.get(Setting.Enable, true); + let inspect = section.inspect(Setting.ExecutablePath); if (inspect && inspect.workspaceValue) { this.executable = inspect.workspaceValue; this.executableIsUserDefined = false; @@ -144,9 +149,9 @@ export default class PHPValidationProvider { this.executable = undefined; this.executableIsUserDefined = undefined; } - this.trigger = RunTrigger.from(section.get('validate.run', RunTrigger.strings.onSave)); + this.trigger = RunTrigger.from(section.get(Setting.Run, RunTrigger.strings.onSave)); } - if (this.executableIsUserDefined !== true && this.workspaceStore.get(CheckedExecutablePath, undefined) !== undefined) { + if (this.executableIsUserDefined !== true && this.workspaceStore.get(Setting.CheckedExecutablePath, undefined) !== undefined) { vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', true); } this.delayers = Object.create(null); @@ -172,7 +177,7 @@ export default class PHPValidationProvider { } private untrustValidationExecutable() { - this.workspaceStore.update(CheckedExecutablePath, undefined); + this.workspaceStore.update(Setting.CheckedExecutablePath, undefined); vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', false); } @@ -196,7 +201,7 @@ export default class PHPValidationProvider { }; if (this.executableIsUserDefined !== undefined && !this.executableIsUserDefined) { - let checkedExecutablePath = this.workspaceStore.get(CheckedExecutablePath, undefined); + let checkedExecutablePath = this.workspaceStore.get(Setting.CheckedExecutablePath, undefined); if (!checkedExecutablePath || checkedExecutablePath !== this.executable) { vscode.window.showInformationMessage( localize('php.useExecutablePath', 'Do you allow {0} (defined as a workspace setting) to be executed to lint PHP files?', this.executable), @@ -213,7 +218,7 @@ export default class PHPValidationProvider { if (!selected || selected.id === 'no') { this.pauseValidation = true; } else if (selected.id === 'yes') { - this.workspaceStore.update(CheckedExecutablePath, this.executable); + this.workspaceStore.update(Setting.CheckedExecutablePath, this.executable); vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', true); trigger(); } @@ -286,7 +291,7 @@ export default class PHPValidationProvider { }); } - private showError(error: any, executable: string): void { + private async showError(error: any, executable: string): Promise { let message: string | null = null; if (error.code === 'ENOENT') { if (this.executable) { @@ -297,8 +302,13 @@ export default class PHPValidationProvider { } else { message = error.message ? error.message : localize('unknownReason', 'Failed to run php using path: {0}. Reason is unknown.', executable); } - if (message) { - vscode.window.showInformationMessage(message); + if (!message) { + return; + } + + const openSettings = localize('goToSetting', 'Open Settings'); + if (await vscode.window.showInformationMessage(message, openSettings) === openSettings) { + vscode.commands.executeCommand('workbench.action.openSettings', Setting.ExecutablePath); } } } From 867bcaee0df6a87ab2f81ef04f24d1e4fe3f6135 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Oct 2019 11:22:13 -0700 Subject: [PATCH 428/435] php - fix identation drifting on empty single-long blocks Fixes https://github.com/microsoft/vscode/issues/34424 --- extensions/php/language-configuration.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index a25868a4175..46101c5aa2f 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -25,7 +25,7 @@ ["`", "`"] ], "indentationRules": { - "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*(/[/*].*)?$", + "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*(/[/*].*)?$", "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" }, "folding": { From 0d065af18569cd81f856ae76fa1efe6f73c68541 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Fri, 11 Oct 2019 11:34:55 -0700 Subject: [PATCH 429/435] adopt font window icon controls (#82301) * adopt font window icon controls fixes #82193 * fix max/restore button --- .../parts/titlebar/media/titlebarpart.css | 43 ++++--------------- .../browser/parts/titlebar/titlebarPart.ts | 25 ++++------- 2 files changed, 18 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css b/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css index 2b1d303976e..992ecca3013 100644 --- a/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css +++ b/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css @@ -106,54 +106,29 @@ .monaco-workbench.fullscreen .part.titlebar > .window-controls-container { display: none; + background-color: transparent; } -.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg { +.monaco-workbench .part.titlebar > .window-controls-container > .window-icon { display: inline-block; - -webkit-app-region: no-drag; + line-height: 30px; height: 100%; - width: 33.34%; + width: 46px; + font-size: 16px; } -.monaco-workbench .part.titlebar > .window-controls-container .window-icon svg { - shape-rendering: crispEdges; - text-align: center; -} - -.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-close { - -webkit-mask: url('chrome-close.svg') no-repeat 50% 50%; -} - -.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-unmaximize { - -webkit-mask: url('chrome-restore.svg') no-repeat 50% 50%; -} - -.monaco-workbench .part.titlebar > .window-controls-container .window-maximize { - -webkit-mask: url('chrome-maximize.svg') no-repeat 50% 50%; -} - -.monaco-workbench .part.titlebar > .window-controls-container .window-minimize { - -webkit-mask: url('chrome-minimize.svg') no-repeat 50% 50%; -} - -.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg > .window-icon { - height: 100%; - width: 100%; - -webkit-mask-size: 23.1%; -} - -.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg:hover { +.monaco-workbench .part.titlebar > .window-controls-container > .window-icon:hover { background-color: rgba(255, 255, 255, 0.1); } -.monaco-workbench .part.titlebar.light > .window-controls-container > .window-icon-bg:hover { +.monaco-workbench .part.titlebar.light > .window-controls-container > .window-icon:hover { background-color: rgba(0, 0, 0, 0.1); } -.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg.window-close-bg:hover { +.monaco-workbench .part.titlebar > .window-controls-container > .window-icon.window-close:hover { background-color: rgba(232, 17, 35, 0.9); } .monaco-workbench .part.titlebar > .window-controls-container .window-icon.window-close:hover { - background-color: white; + color: white; } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index bfc77a7aa5c..55bbb16d9ed 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -413,17 +413,13 @@ export class TitlebarPart extends Part implements ITitleService { this.windowControls = append(this.element, $('div.window-controls-container')); // Minimize - const minimizeIconContainer = append(this.windowControls, $('div.window-icon-bg')); - const minimizeIcon = append(minimizeIconContainer, $('div.window-icon')); - addClass(minimizeIcon, 'window-minimize'); + const minimizeIcon = append(this.windowControls, $('div.window-icon.window-minimize.codicon.codicon-chrome-minimize')); this._register(addDisposableListener(minimizeIcon, EventType.CLICK, e => { this.electronService.minimizeWindow(); })); // Restore - const restoreIconContainer = append(this.windowControls, $('div.window-icon-bg')); - this.maxRestoreControl = append(restoreIconContainer, $('div.window-icon')); - addClass(this.maxRestoreControl, 'window-max-restore'); + this.maxRestoreControl = append(this.windowControls, $('div.window-icon.window-max-restore.codicon')); this._register(addDisposableListener(this.maxRestoreControl, EventType.CLICK, async e => { const maximized = await this.electronService.isMaximized(); if (maximized) { @@ -434,10 +430,7 @@ export class TitlebarPart extends Part implements ITitleService { })); // Close - const closeIconContainer = append(this.windowControls, $('div.window-icon-bg')); - addClass(closeIconContainer, 'window-close-bg'); - const closeIcon = append(closeIconContainer, $('div.window-icon')); - addClass(closeIcon, 'window-close'); + const closeIcon = append(this.windowControls, $('div.window-icon.window-close.codicon.codicon-chrome-close')); this._register(addDisposableListener(closeIcon, EventType.CLICK, e => { this.electronService.closeWindow(); })); @@ -477,11 +470,11 @@ export class TitlebarPart extends Part implements ITitleService { private onDidChangeMaximized(maximized: boolean) { if (this.maxRestoreControl) { if (maximized) { - removeClass(this.maxRestoreControl, 'window-maximize'); - addClass(this.maxRestoreControl, 'window-unmaximize'); + removeClass(this.maxRestoreControl, 'codicon-chrome-maximize'); + addClass(this.maxRestoreControl, 'codicon-chrome-restore'); } else { - removeClass(this.maxRestoreControl, 'window-unmaximize'); - addClass(this.maxRestoreControl, 'window-maximize'); + removeClass(this.maxRestoreControl, 'codicon-chrome-restore'); + addClass(this.maxRestoreControl, 'codicon-chrome-maximize'); } } @@ -621,7 +614,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (titlebarActiveFg) { collector.addRule(` .monaco-workbench .part.titlebar > .window-controls-container .window-icon { - background-color: ${titlebarActiveFg}; + color: ${titlebarActiveFg}; } `); } @@ -630,7 +623,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (titlebarInactiveFg) { collector.addRule(` .monaco-workbench .part.titlebar.inactive > .window-controls-container .window-icon { - background-color: ${titlebarInactiveFg}; + color: ${titlebarInactiveFg}; } `); } From 988077fc2ceeff48c6ba3278e78b5477013c539c Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Fri, 11 Oct 2019 11:55:43 -0700 Subject: [PATCH 430/435] Fix #82298, this.getConnection is not a function --- .../services/telemetry/browser/telemetryService.ts | 9 ++++----- src/vs/workbench/workbench.web.api.ts | 10 ---------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/services/telemetry/browser/telemetryService.ts b/src/vs/workbench/services/telemetry/browser/telemetryService.ts index aaea9e997d8..0c62adace7c 100644 --- a/src/vs/workbench/services/telemetry/browser/telemetryService.ts +++ b/src/vs/workbench/services/telemetry/browser/telemetryService.ts @@ -19,20 +19,20 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA export class WebTelemetryAppender implements ITelemetryAppender { - constructor(private _logService: ILogService, private _appender: ITelemetryAppender) { } + constructor(private _logService: ILogService, private _appender: IRemoteAgentService) { } log(eventName: string, data: any): void { data = validateTelemetryData(data); this._logService.trace(`telemetry/${eventName}`, data); - this._appender.log('/monacoworkbench/' + eventName, { + this._appender.logTelemetry('/monacoworkbench/' + eventName, { properties: data.properties, measurements: data.measurements }); } flush(): Promise { - return this._appender.flush(); + return this._appender.flushTelemetry(); } } @@ -53,9 +53,8 @@ export class TelemetryService extends Disposable implements ITelemetryService { super(); if (!environmentService.args['disable-telemetry'] && !!productService.enableTelemetry) { - const telemetryProvider = environmentService.options && environmentService.options.telemetryAppender || { log: remoteAgentService.logTelemetry, flush: remoteAgentService.flushTelemetry }; const config: ITelemetryServiceConfig = { - appender: combinedAppender(new WebTelemetryAppender(logService, telemetryProvider), new LogAppender(logService)), + appender: combinedAppender(new WebTelemetryAppender(logService, remoteAgentService), new LogAppender(logService)), commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority), piiPaths: [environmentService.appRoot] }; diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index 3c30b2fd899..0140a8cec27 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -15,7 +15,6 @@ import { LogLevel } from 'vs/platform/log/common/log'; import { IUpdateProvider, IUpdate } from 'vs/workbench/services/update/browser/updateService'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils'; import { IWorkspaceProvider, IWorkspace } from 'vs/workbench/services/host/browser/browserHostService'; interface IWorkbenchConstructionOptions { @@ -89,12 +88,6 @@ interface IWorkbenchConstructionOptions { */ updateProvider?: IUpdateProvider; - /** - * Experimental: If provided, will be called when logging telemetry events. - */ - telemetryAppender?: ITelemetryAppender; - - /** * Experimental: Support adding additional properties to telemetry. */ @@ -159,7 +152,4 @@ export { // Updates IUpdateProvider, IUpdate, - - // Telemetry - ITelemetryAppender }; From b6b011b2946a90586a31bc3c097571f9a21632ad Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Oct 2019 11:56:21 -0700 Subject: [PATCH 431/435] php - increment indentation for inline php tags Fixes https://github.com/microsoft/vscode/issues/44137 --- extensions/php/language-configuration.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 46101c5aa2f..9c24c7b724b 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -25,7 +25,7 @@ ["`", "`"] ], "indentationRules": { - "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*(/[/*].*)?$", + "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*((/[/*].*|)?$|\\?>)", "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" }, "folding": { From 78fd1e5ec2efa9bd2656f1079d9d9ed88b7e39a0 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 11 Oct 2019 13:36:36 -0700 Subject: [PATCH 432/435] php - fix break statement not reducing indent level Fixes https://github.com/microsoft/vscode/issues/57964 --- extensions/php/language-configuration.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 9c24c7b724b..b9b67d2be50 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -26,7 +26,7 @@ ], "indentationRules": { "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*((/[/*].*|)?$|\\?>)", - "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" + "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch)|break);))" }, "folding": { "markers": { From 1f01e888f2fe0262524a71cd5decbcb07741fdc8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 12 Oct 2019 00:22:46 +0200 Subject: [PATCH 433/435] debt - Avoid Number.MIN_VALUE and Number.MAX_VALUE --- src/vs/base/common/diff/diff.ts | 13 ++++----- .../common/core => base/common}/uint.ts | 26 ------------------ .../contentWidgets/contentWidgets.ts | 2 +- .../browser/viewParts/lines/rangeUtil.ts | 2 +- .../browser/viewParts/lines/viewLines.ts | 3 ++- .../editor/browser/widget/diffEditorWidget.ts | 17 ++++++------ src/vs/editor/common/config/editorOptions.ts | 2 +- .../editor/common/core/characterClassifier.ts | 2 +- src/vs/editor/common/modes/linkComputer.ts | 27 ++++++++++++++++++- .../common/viewLayout/lineDecorations.ts | 2 +- .../characterHardWrappingLineMapper.ts | 2 +- .../common/viewModel/prefixSumComputer.ts | 2 +- .../contrib/comment/lineCommentCommand.ts | 3 ++- src/vs/editor/contrib/find/findModel.ts | 2 +- .../editor/contrib/hover/modesContentHover.ts | 3 ++- .../editor/contrib/multicursor/multicursor.ts | 2 +- .../referenceSearch/referencesModel.ts | 3 ++- .../viewModel/prefixSumComputer.test.ts | 2 +- .../viewModel/splitLinesCollection.test.ts | 2 +- .../contrib/debug/browser/breakpointsView.ts | 2 +- .../browser/debugCallStackContribution.ts | 2 +- .../debug/browser/debugEditorContribution.ts | 2 +- .../contrib/files/browser/fileActions.ts | 2 +- 23 files changed, 65 insertions(+), 60 deletions(-) rename src/vs/{editor/common/core => base/common}/uint.ts (74%) diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index 0183b199249..abe78fbd8be 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -5,6 +5,7 @@ import { DiffChange } from 'vs/base/common/diff/diffChange'; import { stringHash } from 'vs/base/common/hash'; +import { Constants } from 'vs/base/common/uint'; export class StringDiffSequence implements ISequence { @@ -138,8 +139,8 @@ class DiffChangeHelper { */ constructor() { this.m_changes = []; - this.m_originalStart = Number.MAX_VALUE; - this.m_modifiedStart = Number.MAX_VALUE; + this.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER; + this.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER; this.m_originalCount = 0; this.m_modifiedCount = 0; } @@ -158,8 +159,8 @@ class DiffChangeHelper { // Reset for the next change this.m_originalCount = 0; this.m_modifiedCount = 0; - this.m_originalStart = Number.MAX_VALUE; - this.m_modifiedStart = Number.MAX_VALUE; + this.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER; + this.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER; } /** @@ -422,7 +423,7 @@ export class LcsDiff { let diagonalMin = diagonalForwardStart; let diagonalMax = diagonalForwardEnd; let diagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalForwardOffset; - let lastOriginalIndex = Number.MIN_VALUE; + let lastOriginalIndex = Constants.MIN_SAFE_SMALL_INTEGER; let historyIndex = this.m_forwardHistory.length - 1; let diagonal: number; @@ -488,7 +489,7 @@ export class LcsDiff { diagonalMin = diagonalReverseStart; diagonalMax = diagonalReverseEnd; diagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalReverseOffset; - lastOriginalIndex = Number.MAX_VALUE; + lastOriginalIndex = Constants.MAX_SAFE_SMALL_INTEGER; historyIndex = (deltaIsEven) ? this.m_reverseHistory.length - 1 : this.m_reverseHistory.length - 2; do { diff --git a/src/vs/editor/common/core/uint.ts b/src/vs/base/common/uint.ts similarity index 74% rename from src/vs/editor/common/core/uint.ts rename to src/vs/base/common/uint.ts index 00e3b872903..0f5a4f8930a 100644 --- a/src/vs/editor/common/core/uint.ts +++ b/src/vs/base/common/uint.ts @@ -3,32 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export class Uint8Matrix { - - private readonly _data: Uint8Array; - public readonly rows: number; - public readonly cols: number; - - constructor(rows: number, cols: number, defaultValue: number) { - const data = new Uint8Array(rows * cols); - for (let i = 0, len = rows * cols; i < len; i++) { - data[i] = defaultValue; - } - - this._data = data; - this.rows = rows; - this.cols = cols; - } - - public get(row: number, col: number): number { - return this._data[row * this.cols + col]; - } - - public set(row: number, col: number, value: number): void { - this._data[row * this.cols + col] = value; - } -} - export const enum Constants { /** * MAX SMI (SMall Integer) as defined in v8. diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index eb49a439f9d..e98cea19e9c 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -9,7 +9,7 @@ import { ContentWidgetPositionPreference, IContentWidget } from 'vs/editor/brows import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; import { ViewContext } from 'vs/editor/common/view/viewContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; diff --git a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts index 5344effa706..f84a79df8d4 100644 --- a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts +++ b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; class FloatHorizontalRange { diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index eb524a41b69..ff3a504d5cf 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -20,6 +20,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { Viewport } from 'vs/editor/common/viewModel/viewModel'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { Constants } from 'vs/base/common/uint'; class LastRenderedData { @@ -641,7 +642,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, const viewportEndX = viewportStartX + viewport.width; const visibleRanges = this.visibleRangesForRange2(new Range(lineNumber, startColumn, lineNumber, endColumn)); - let boxStartX = Number.MAX_VALUE; + let boxStartX = Constants.MAX_SAFE_SMALL_INTEGER; let boxEndX = 0; if (!visibleRanges) { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index d1bc2ad7820..89b8bf72d30 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -43,6 +43,7 @@ import { ITheme, IThemeService, getThemeTypeSelector, registerThemingParticipant import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDiffLinesChange, InlineDiffMargin } from 'vs/editor/browser/widget/inlineDiffMargin'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { Constants } from 'vs/base/common/uint'; interface IEditorDiffDecorations { decorations: IModelDeltaDecoration[]; @@ -1122,7 +1123,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE while (min < max) { let mid = Math.floor((min + max) / 2); let midStart = startLineNumberExtractor(lineChanges[mid]); - let midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Number.MAX_VALUE); + let midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Constants.MAX_SAFE_SMALL_INTEGER); if (lineNumber < midStart) { max = mid - 1; @@ -1682,11 +1683,11 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE if (isChangeOrDelete(lineChange)) { result.decorations.push({ - range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineDeleteWithSign : DECORATIONS.lineDelete) }); if (!isChangeOrInsert(lineChange) || !lineChange.charChanges) { - result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, DECORATIONS.charDeleteWholeLine)); + result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charDeleteWholeLine)); } result.overviewZones.push(new OverviewRulerZone( @@ -1743,11 +1744,11 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE if (isChangeOrInsert(lineChange)) { result.decorations.push({ - range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { - result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); + result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charInsertWholeLine)); } result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, @@ -1861,7 +1862,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito // Add overview zones in the overview ruler if (isChangeOrDelete(lineChange)) { result.decorations.push({ - range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: DECORATIONS.lineDeleteMargin }); @@ -1892,7 +1893,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito // Add decorations & overview zones if (isChangeOrInsert(lineChange)) { result.decorations.push({ - range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); @@ -1928,7 +1929,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito } } } else { - result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); + result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charInsertWholeLine)); } } } diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 2b39a750360..44a7959ddcf 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { isObject } from 'vs/base/common/types'; diff --git a/src/vs/editor/common/core/characterClassifier.ts b/src/vs/editor/common/core/characterClassifier.ts index 9d448641d17..214bb2abf05 100644 --- a/src/vs/editor/common/core/characterClassifier.ts +++ b/src/vs/editor/common/core/characterClassifier.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { toUint8 } from 'vs/editor/common/core/uint'; +import { toUint8 } from 'vs/base/common/uint'; /** * A fast character classifier that uses a compact array for ASCII values. diff --git a/src/vs/editor/common/modes/linkComputer.ts b/src/vs/editor/common/modes/linkComputer.ts index 00bf7d01b36..6673c04f64a 100644 --- a/src/vs/editor/common/modes/linkComputer.ts +++ b/src/vs/editor/common/modes/linkComputer.ts @@ -5,7 +5,6 @@ import { CharCode } from 'vs/base/common/charCode'; import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier'; -import { Uint8Matrix } from 'vs/editor/common/core/uint'; import { ILink } from 'vs/editor/common/modes'; export interface ILinkComputerTarget { @@ -33,6 +32,32 @@ export const enum State { export type Edge = [State, number, State]; +export class Uint8Matrix { + + private readonly _data: Uint8Array; + public readonly rows: number; + public readonly cols: number; + + constructor(rows: number, cols: number, defaultValue: number) { + const data = new Uint8Array(rows * cols); + for (let i = 0, len = rows * cols; i < len; i++) { + data[i] = defaultValue; + } + + this._data = data; + this.rows = rows; + this.cols = cols; + } + + public get(row: number, col: number): number { + return this._data[row * this.cols + col]; + } + + public set(row: number, col: number, value: number): void { + this._data[row * this.cols + col] = value; + } +} + export class StateMachine { private readonly _states: Uint8Matrix; diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index cae03bc9e46..a384c18a977 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as strings from 'vs/base/common/strings'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; import { equals } from 'vs/base/common/arrays'; diff --git a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts index 74b236d4b78..bbf71e817b9 100644 --- a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts +++ b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts @@ -7,7 +7,7 @@ import { CharCode } from 'vs/base/common/charCode'; import * as strings from 'vs/base/common/strings'; import { WrappingIndent } from 'vs/editor/common/config/editorOptions'; import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { ILineMapperFactory, ILineMapping, OutputPosition } from 'vs/editor/common/viewModel/splitLinesCollection'; diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts index 81e66ac5059..d4e8c1f0df2 100644 --- a/src/vs/editor/common/viewModel/prefixSumComputer.ts +++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { toUint32 } from 'vs/editor/common/core/uint'; +import { toUint32 } from 'vs/base/common/uint'; export class PrefixSumIndexOfResult { _prefixSumIndexOfResultBrand: void; diff --git a/src/vs/editor/contrib/comment/lineCommentCommand.ts b/src/vs/editor/contrib/comment/lineCommentCommand.ts index a097d994648..5c3716ed79c 100644 --- a/src/vs/editor/contrib/comment/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/lineCommentCommand.ts @@ -13,6 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { BlockCommentCommand } from 'vs/editor/contrib/comment/blockCommentCommand'; +import { Constants } from 'vs/base/common/uint'; export interface IInsertionPoint { ignore: boolean; @@ -392,7 +393,7 @@ export class LineCommentCommand implements editorCommon.ICommand { * Adjust insertion points to have them vertically aligned in the add line comment case */ public static _normalizeInsertionPoint(model: ISimpleModel, lines: IInsertionPoint[], startLineNumber: number, tabSize: number): void { - let minVisibleColumn = Number.MAX_VALUE; + let minVisibleColumn = Constants.MAX_SAFE_SMALL_INTEGER; let j: number; let lenJ: number; diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index e039801431f..da67f86eb78 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -12,7 +12,7 @@ import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/commo 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 { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { EndOfLinePreference, FindMatch, ITextModel } from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 06877b671d5..8dae61e55d0 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -38,6 +38,7 @@ import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { Constants } from 'vs/base/common/uint'; const $ = dom.$; @@ -333,7 +334,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this._colorPicker = null; // update column from which to show - let renderColumn = Number.MAX_VALUE; + let renderColumn = Constants.MAX_SAFE_SMALL_INTEGER; let highlightRange: Range | null = messages[0].range ? Range.lift(messages[0].range) : null; let fragment = document.createDocumentFragment(); let isEmptyHoverContent = true; diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index a76a1d62e96..11516c57f83 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -14,7 +14,7 @@ import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/comm import { CursorMoveCommands } from 'vs/editor/common/controller/cursorMoveCommands'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { FindMatch, ITextModel, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model'; diff --git a/src/vs/editor/contrib/referenceSearch/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/referencesModel.ts index 36d54e60852..579625ed01d 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesModel.ts @@ -15,6 +15,7 @@ import { Location, LocationLink } from 'vs/editor/common/modes'; import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { Position } from 'vs/editor/common/core/position'; import { IMatch } from 'vs/base/common/filters'; +import { Constants } from 'vs/base/common/uint'; export class OneReference { readonly id: string; @@ -72,7 +73,7 @@ export class FilePreview implements IDisposable { const { startLineNumber, startColumn, endLineNumber, endColumn } = range; const word = model.getWordUntilPosition({ lineNumber: startLineNumber, column: startColumn - n }); const beforeRange = new Range(startLineNumber, word.startColumn, startLineNumber, startColumn); - const afterRange = new Range(endLineNumber, endColumn, endLineNumber, Number.MAX_VALUE); + const afterRange = new Range(endLineNumber, endColumn, endLineNumber, Constants.MAX_SAFE_SMALL_INTEGER); const before = model.getValueInRange(beforeRange).replace(/^\s+/, ''); const inside = model.getValueInRange(range); diff --git a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts index 11cc42efb8d..313c672b101 100644 --- a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { PrefixSumComputer, PrefixSumIndexOfResult } from 'vs/editor/common/viewModel/prefixSumComputer'; suite('Editor ViewModel - PrefixSumComputer', () => { diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index d57bcaecded..a8b64c4da7a 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -9,7 +9,7 @@ import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { TokenizationResult2 } from 'vs/editor/common/core/token'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { EndOfLinePreference } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import * as modes from 'vs/editor/common/modes'; diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 7f8ffb936c3..624002135be 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -14,7 +14,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IListVirtualDelegate, IListContextMenuEvent, IListRenderer } from 'vs/base/browser/ui/list/list'; diff --git a/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts b/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts index 68cf65a7931..d102042652b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { Range } from 'vs/editor/common/core/range'; import { ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/model'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index a395d10adc1..3b7f7be2ce8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as env from 'vs/base/common/platform'; import { visit } from 'vs/base/common/json'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardTokenType } from 'vs/editor/common/modes'; diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 3768bc96d17..e44827d52c1 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -39,7 +39,7 @@ import { Schemas } from 'vs/base/common/network'; import { IDialogService, IConfirmationResult, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { CLOSE_EDITORS_AND_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { coalesce } from 'vs/base/common/arrays'; import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; From 34e03dda661374d8224f0dc0127cb78accf5f1bc Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 12 Oct 2019 00:34:11 +0200 Subject: [PATCH 434/435] Fixes #63553: Repaint decorations when the modified editor's tab size changes --- src/vs/editor/browser/widget/diffEditorWidget.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 89b8bf72d30..fd88b9e0eab 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -492,6 +492,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE } })); + this._register(editor.onDidChangeModelOptions((e) => { + if (e.tabSize) { + this._updateDecorationsRunner.schedule(); + } + })); + return editor; } @@ -647,6 +653,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this.modifiedEditor.setModel(model ? model.modified : null); this._updateDecorationsRunner.cancel(); + // this.originalEditor.onDidChangeModelOptions + if (model) { this.originalEditor.setScrollTop(0); this.modifiedEditor.setScrollTop(0); From c8fe7709a732afe30c08a476be42292b2f6c4611 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 12 Oct 2019 00:35:35 +0200 Subject: [PATCH 435/435] Fixes #64579 --- src/vs/editor/browser/widget/diffEditorWidget.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index fd88b9e0eab..90f3acdf3cc 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -998,7 +998,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private _adjustOptionsForLeftHandSide(options: IDiffEditorOptions, isEditable: boolean): IEditorOptions { let result = this._adjustOptionsForSubEditor(options); result.readOnly = !isEditable; - result.overviewRulerLanes = 1; result.extraEditorClassName = 'original-in-monaco-diff-editor'; return result; }