From 354956f6382236000f2272da2e4a513d74dabcef Mon Sep 17 00:00:00 2001 From: parkourkarthik Date: Wed, 10 Oct 2018 08:38:30 +0530 Subject: [PATCH 001/172] include uri to open file cmd on clean tree --- extensions/git/src/commands.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 9c838715840..4dbc3784806 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -608,6 +608,9 @@ export class CommandCenter { uris = resources.map(r => r.resourceUri); } + else { + uris = [(window.activeTextEditor && window.activeTextEditor.document.uri)] as Uri[]; + } } if (!uris) { From dce56c504c08ab5e63fda05b793c581fac2a0851 Mon Sep 17 00:00:00 2001 From: Pawel Urbanski Date: Tue, 22 Jan 2019 19:43:58 +0100 Subject: [PATCH 002/172] Assigned an empty string to silence too verbose alerts, which try to handle function, much better handled by the screen readers, and therefore they should be removed. --- src/vs/editor/contrib/suggest/suggestController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 05e535ac302..9f9f2594ef0 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -292,7 +292,8 @@ export class SuggestController implements IEditorContribution { } private _alertCompletionItem({ completion: suggestion }: CompletionItem): void { - let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' did insert the following text: {1}", suggestion.label, suggestion.insertText); + // @todo Remove alert support. Assigning an empty string temporarly to silence alers. + let msg = null; alert(msg); } From 700de5683e0072561cbc11d175c4f1533df934b3 Mon Sep 17 00:00:00 2001 From: Pawel Urbanski Date: Tue, 22 Jan 2019 21:11:40 +0100 Subject: [PATCH 003/172] Changed verbosity of code completion widget alerts to provide the current completion item without unnecesary snippet/regular hints, or if items have details. --- src/vs/editor/contrib/suggest/suggestWidget.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 347de4b6499..57c53a281bf 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -535,23 +535,25 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate { this.onDidSelectEmitter.fire({ item, index, model: completionModel }); - alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.completion.label)); this.editor.focus(); }); } private _getSuggestionAriaAlertLabel(item: CompletionItem): string { + // It is not so important to know the type of completion: regular or snippet. + // Snippets can be identified by their names. + // They are usually created by users themselves. const isSnippet = item.completion.kind === CompletionItemKind.Snippet; if (!canExpandCompletionItem(item)) { - return isSnippet ? nls.localize('ariaCurrentSnippetSuggestion', "{0}, snippet suggestion", item.completion.label) - : nls.localize('ariaCurrentSuggestion', "{0}, suggestion", item.completion.label); + return isSnippet ? item.completion.label + : item.completion.label; } else if (this.expandDocsSettingFromStorage()) { - return isSnippet ? nls.localize('ariaCurrentSnippeSuggestionReadDetails', "{0}, snippet suggestion. Reading details. {1}", item.completion.label, this.details.getAriaLabel()) - : nls.localize('ariaCurrenttSuggestionReadDetails', "{0}, suggestion. Reading details. {1}", item.completion.label, this.details.getAriaLabel()); + return isSnippet ? nls.localize('ariaCurrentSnippeSuggestionReadDetails', "{0}: {1}", item.completion.label, this.details.getAriaLabel()) + : nls.localize('ariaCurrenttSuggestionReadDetails', "{0}: {1}", item.completion.label, this.details.getAriaLabel()); } else { - return isSnippet ? nls.localize('ariaCurrentSnippetSuggestionWithDetails', "{0}, snippet suggestion, has details", item.completion.label) - : nls.localize('ariaCurrentSuggestionWithDetails', "{0}, suggestion, has details", item.completion.label); + return isSnippet ? item.completion.label + : item.completion.label; } } From 12c69a6475e5ca4a7d4a8611b0cecbb387391679 Mon Sep 17 00:00:00 2001 From: Pawel Urbanski Date: Fri, 25 Jan 2019 17:11:00 +0100 Subject: [PATCH 004/172] Removed reporting the number of times alerted string appeared, which has no use for a blind user, and causes too much verbosity. --- src/vs/base/browser/ui/aria/aria.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/vs/base/browser/ui/aria/aria.ts b/src/vs/base/browser/ui/aria/aria.ts index 1922450144d..d7dad9cba5c 100644 --- a/src/vs/base/browser/ui/aria/aria.ts +++ b/src/vs/base/browser/ui/aria/aria.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./aria'; -import * as nls from 'vs/nls'; import { isMacintosh } from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; @@ -48,29 +47,12 @@ export function status(msg: string): void { } } -let repeatedTimes = 0; -let prevText: string | undefined = undefined; function insertMessage(target: HTMLElement, msg: string): void { if (!ariaContainer) { // console.warn('ARIA support needs a container. Call setARIAContainer() first.'); return; } - if (prevText === msg) { - repeatedTimes++; - } - else { - prevText = msg; - repeatedTimes = 0; - } - - - switch (repeatedTimes) { - case 0: break; - case 1: msg = nls.localize('repeated', "{0} (occurred again)", msg); break; - default: msg = nls.localize('repeatedNtimes', "{0} (occurred {1} times)", msg, repeatedTimes); break; - } - dom.clearNode(target); target.textContent = msg; From c3269a3966017a08077d3bbeee50905d416bffdd Mon Sep 17 00:00:00 2001 From: Pawel Urbanski Date: Fri, 25 Jan 2019 17:43:10 +0100 Subject: [PATCH 005/172] Changes to how documentation strings are presented. Includes previous fixes to alerts. --- src/vs/editor/contrib/suggest/suggestWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 57c53a281bf..8de80617e8d 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -549,8 +549,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate Date: Mon, 28 Jan 2019 20:08:06 +0100 Subject: [PATCH 006/172] Fixes duplicating screen reader features with alert - needs further code refactoring. --- src/vs/editor/contrib/suggest/suggestController.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 9f9f2594ef0..20f37c560e0 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { alert } from 'vs/base/browser/ui/aria/aria'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; @@ -292,9 +291,8 @@ export class SuggestController implements IEditorContribution { } private _alertCompletionItem({ completion: suggestion }: CompletionItem): void { - // @todo Remove alert support. Assigning an empty string temporarly to silence alers. - let msg = null; - alert(msg); + // A temporary fix for too verbose, unnecesary screen reader alerts. + // Todo: Remove calls to this empty method body. } triggerSuggest(onlyFrom?: CompletionItemProvider[]): void { From 5af1f510ccfcb706b0e57ddfa8aaa86522e04f3c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 27 Feb 2019 14:41:54 +0100 Subject: [PATCH 007/172] save untitled workspace on renderer --- src/vs/code/electron-main/windows.ts | 113 +------------- src/vs/platform/windows/common/windows.ts | 2 +- .../windows/electron-main/windowsService.ts | 10 +- src/vs/platform/windows/node/windowsIpc.ts | 6 +- .../platform/workspaces/common/workspaces.ts | 4 +- .../electron-main/workspacesMainService.ts | 34 +--- .../platform/workspaces/node/workspacesIpc.ts | 8 + .../workspacesMainService.test.ts | 147 ++++++++---------- src/vs/workbench/browser/dnd.ts | 2 +- .../workspace/common/workspaceEditing.ts | 5 + .../workspace/node/workspaceEditingService.ts | 114 +++++++++++++- .../workbench/test/workbenchTestServices.ts | 2 +- 12 files changed, 208 insertions(+), 239 deletions(-) diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 59bfccd1142..2e94e6cfaed 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -25,14 +25,14 @@ import product from 'vs/platform/product/node/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 { IHistoryMainService } from 'vs/platform/history/common/history'; -import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; +import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension } 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 { normalizeNFC } from 'vs/base/common/normalization'; import { URI } from 'vs/base/common/uri'; -import { Queue, timeout } from 'vs/base/common/async'; +import { Queue } from 'vs/base/common/async'; import { exists } from 'vs/base/node/pfs'; import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; @@ -197,7 +197,7 @@ export class WindowsManager implements IWindowsMainService { } this.dialogs = new Dialogs(environmentService, telemetryService, stateService, this); - this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, environmentService, historyMainService, this); + this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this); } ready(initialUserEnv: IProcessEnvironment): void { @@ -1544,23 +1544,6 @@ export class WindowsManager implements IWindowsMainService { this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); return; } - - if (windowClosing && !isMacintosh && this.getWindowCount() === 1) { - return; // Windows/Linux: quits when last window is closed, so do not ask then - } - - // Handle untitled workspaces with prompt as needed - e.veto(this.workspacesManager.promptToSaveUntitledWorkspace(this.getWindowById(e.window.id), workspace).then((veto): boolean | Promise => { - if (veto) { - return veto; - } - - // Bug in electron: somehow we need this timeout so that the window closes properly. That - // might be related to the fact that the untitled workspace prompt shows up async and this - // code can execute before the dialog is fully closed which then blocks the window from closing. - // Issue: https://github.com/Microsoft/vscode/issues/41989 - return timeout(0).then(() => veto); - })); } focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { @@ -1994,8 +1977,6 @@ class WorkspacesManager { constructor( private readonly workspacesMainService: IWorkspacesMainService, private readonly backupMainService: IBackupMainService, - private readonly environmentService: IEnvironmentService, - private readonly historyMainService: IHistoryMainService, private readonly windowsMainService: IWindowsMainService, ) { } @@ -2079,92 +2060,4 @@ class WorkspacesManager { telemetryExtraData: options.telemetryExtraData }); } - - promptToSaveUntitledWorkspace(window: ICodeWindow | undefined, workspace: IWorkspaceIdentifier): Promise { - enum ConfirmResult { - SAVE, - DONT_SAVE, - CANCEL - } - - const save = { label: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), result: ConfirmResult.SAVE }; - const dontSave = { label: mnemonicButtonLabel(localize({ key: 'doNotSave', comment: ['&& denotes a mnemonic'] }, "Do&&n't Save")), result: ConfirmResult.DONT_SAVE }; - const cancel = { label: localize('cancel', "Cancel"), result: ConfirmResult.CANCEL }; - - const buttons: { label: string; result: ConfirmResult; }[] = []; - if (isWindows) { - buttons.push(save, dontSave, cancel); - } else if (isLinux) { - buttons.push(dontSave, cancel, save); - } else { - buttons.push(save, cancel, dontSave); - } - - const options: Electron.MessageBoxOptions = { - title: this.environmentService.appNameLong, - message: localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"), - detail: localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."), - noLink: true, - type: 'warning', - buttons: buttons.map(button => button.label), - cancelId: buttons.indexOf(cancel) - }; - - if (isLinux) { - options.defaultId = 2; - } - - return this.windowsMainService.showMessageBox(options, window).then(res => { - switch (buttons[res.button].result) { - - // Cancel: veto unload - case ConfirmResult.CANCEL: - return true; - - // Don't Save: delete workspace - case ConfirmResult.DONT_SAVE: - this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); - return false; - - // Save: save workspace, but do not veto unload - case ConfirmResult.SAVE: { - return this.windowsMainService.showSaveDialog({ - buttonLabel: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), - title: localize('saveWorkspace', "Save Workspace"), - filters: WORKSPACE_FILTER, - defaultPath: this.getUntitledWorkspaceSaveDialogDefaultPath(workspace) - }, window).then(target => { - if (target) { - return this.workspacesMainService.saveWorkspaceAs(workspace, target).then(savedWorkspace => { - this.historyMainService.addRecentlyOpened([savedWorkspace], []); - this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); - return false; - }, () => false); - } - - return true; // keep veto if no target was provided - }); - } - } - }); - } - - private getUntitledWorkspaceSaveDialogDefaultPath(workspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier): string | undefined { - if (workspace) { - if (isSingleFolderWorkspaceIdentifier(workspace)) { - return workspace.scheme === Schemas.file ? dirname(workspace.fsPath) : undefined; - } - - const resolvedWorkspace = workspace.configPath.scheme === Schemas.file && this.workspacesMainService.resolveLocalWorkspaceSync(workspace.configPath); - if (resolvedWorkspace && resolvedWorkspace.folders.length > 0) { - for (const folder of resolvedWorkspace.folders) { - if (folder.uri.scheme === Schemas.file) { - return dirname(folder.uri.fsPath); - } - } - } - } - - return undefined; - } } diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index e28ca55477a..a39720ec134 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -117,7 +117,7 @@ export interface IWindowsService { enterWorkspace(windowId: number, path: URI): Promise; toggleFullScreen(windowId: number): Promise; setRepresentedFilename(windowId: number, fileName: string): Promise; - addRecentlyOpened(files: URI[]): Promise; + addRecentlyOpened(workspaces: URI[], folders: URI[], files: URI[]): Promise; removeFromRecentlyOpened(paths: Array): Promise; clearRecentlyOpened(): Promise; getRecentlyOpened(windowId: number): Promise; diff --git a/src/vs/platform/windows/electron-main/windowsService.ts b/src/vs/platform/windows/electron-main/windowsService.ts index 016c59a3f20..9223005e842 100644 --- a/src/vs/platform/windows/electron-main/windowsService.ts +++ b/src/vs/platform/windows/electron-main/windowsService.ts @@ -17,7 +17,7 @@ import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IWindowsMainService, ISharedProcess, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { IHistoryMainService, IRecentlyOpened } from 'vs/platform/history/common/history'; -import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { Schemas } from 'vs/base/common/network'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; @@ -50,7 +50,8 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable @IURLService urlService: IURLService, @ILifecycleService private readonly lifecycleService: ILifecycleService, @IHistoryMainService private readonly historyService: IHistoryMainService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, ) { urlService.registerHandler(this); @@ -156,10 +157,11 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable return this.withWindow(windowId, codeWindow => codeWindow.setRepresentedFilename(fileName)); } - async addRecentlyOpened(files: URI[]): Promise { + async addRecentlyOpened(workspaces: URI[], folders: URI[], files: URI[]): Promise { this.logService.trace('windowsService#addRecentlyOpened'); - this.historyService.addRecentlyOpened(undefined, files); + const workspaceIdentifiers = workspaces.map(w => this.workspacesMainService.getWorkspaceIdentifier(w)); + this.historyService.addRecentlyOpened([...workspaceIdentifiers, ...folders], files); } async removeFromRecentlyOpened(paths: Array): Promise { diff --git a/src/vs/platform/windows/node/windowsIpc.ts b/src/vs/platform/windows/node/windowsIpc.ts index 12b741138c0..cece368e7a0 100644 --- a/src/vs/platform/windows/node/windowsIpc.ts +++ b/src/vs/platform/windows/node/windowsIpc.ts @@ -59,7 +59,7 @@ export class WindowsChannel implements IServerChannel { case 'enterWorkspace': return this.service.enterWorkspace(arg[0], URI.revive(arg[1])); case 'toggleFullScreen': return this.service.toggleFullScreen(arg); case 'setRepresentedFilename': return this.service.setRepresentedFilename(arg[0], arg[1]); - case 'addRecentlyOpened': return this.service.addRecentlyOpened(arg.map(URI.revive)); + case 'addRecentlyOpened': return this.service.addRecentlyOpened(arg[0].map(URI.revive), arg[1].map(URI.revive), arg[2].map(URI.revive)); case 'removeFromRecentlyOpened': { let paths: Array = arg; if (Array.isArray(paths)) { @@ -178,8 +178,8 @@ export class WindowsChannelClient implements IWindowsService { return this.channel.call('setRepresentedFilename', [windowId, fileName]); } - addRecentlyOpened(files: URI[]): Promise { - return this.channel.call('addRecentlyOpened', files); + addRecentlyOpened(workspaces: URI[], folders: URI[], files: URI[]): Promise { + return this.channel.call('addRecentlyOpened', [workspaces, folders, files]); } removeFromRecentlyOpened(paths: Array): Promise { diff --git a/src/vs/platform/workspaces/common/workspaces.ts b/src/vs/platform/workspaces/common/workspaces.ts index dab9dd39404..b72fe85d629 100644 --- a/src/vs/platform/workspaces/common/workspaces.ts +++ b/src/vs/platform/workspaces/common/workspaces.ts @@ -96,8 +96,6 @@ export interface IWorkspacesMainService extends IWorkspacesService { onUntitledWorkspaceDeleted: Event; - saveWorkspaceAs(workspace: IWorkspaceIdentifier, target: string): Promise; - createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier; resolveLocalWorkspaceSync(path: URI): IResolvedWorkspace | null; @@ -115,6 +113,8 @@ export interface IWorkspacesService { _serviceBrand: any; createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[]): Promise; + + deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise; } export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier { diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index d61031e0e9d..d0d80e3b846 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -3,16 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IWorkspacesMainService, IWorkspaceIdentifier, hasWorkspaceFileExtension, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, rewriteWorkspaceFileForNewLocation, IUntitledWorkspaceInfo, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspacesMainService, IWorkspaceIdentifier, hasWorkspaceFileExtension, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, IUntitledWorkspaceInfo, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { join, dirname } from 'vs/base/common/path'; -import { mkdirp, writeFile, readFile } from 'vs/base/node/pfs'; +import { mkdirp, writeFile } from 'vs/base/node/pfs'; import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs'; import { isLinux } from 'vs/base/common/platform'; import { delSync, readdirSync, writeFileAndFlushSync } from 'vs/base/node/extfs'; import { Event, Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; -import { isEqual } from 'vs/base/common/extpath'; import { createHash } from 'crypto'; import * as json from 'vs/base/common/json'; import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; @@ -168,30 +167,6 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain return this.isInsideWorkspacesHome(workspace.configPath); } - saveWorkspaceAs(workspace: IWorkspaceIdentifier, targetConfigPath: string): Promise { - - if (workspace.configPath.scheme !== Schemas.file) { - throw new Error('Only local workspaces can be saved with this API. Use WorkspaceEditingService.saveWorkspaceAs on the renderer instead.'); - } - - const configPath = originalFSPath(workspace.configPath); - - // Return early if target is same as source - if (isEqual(configPath, targetConfigPath, !isLinux)) { - return Promise.resolve(workspace); - } - - // Read the contents of the workspace file and resolve it - return readFile(configPath).then(raw => { - const targetConfigPathURI = URI.file(targetConfigPath); - const newRawWorkspaceContents = rewriteWorkspaceFileForNewLocation(raw.toString(), workspace.configPath, targetConfigPathURI); - - return writeFile(targetConfigPath, newRawWorkspaceContents).then(() => { - return this.getWorkspaceIdentifier(targetConfigPathURI); - }); - }); - } - deleteUntitledWorkspaceSync(workspace: IWorkspaceIdentifier): void { if (!this.isUntitledWorkspace(workspace)) { return; // only supported for untitled workspaces @@ -204,6 +179,11 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain this._onUntitledWorkspaceDeleted.fire(workspace); } + deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise { + this.deleteUntitledWorkspaceSync(workspace); + return Promise.resolve(); + } + private doDeleteUntitledWorkspaceSync(workspace: IWorkspaceIdentifier): void { const configPath = originalFSPath(workspace.configPath); try { diff --git a/src/vs/platform/workspaces/node/workspacesIpc.ts b/src/vs/platform/workspaces/node/workspacesIpc.ts index 11ae4da17ec..6d1af4e5457 100644 --- a/src/vs/platform/workspaces/node/workspacesIpc.ts +++ b/src/vs/platform/workspaces/node/workspacesIpc.ts @@ -32,6 +32,10 @@ export class WorkspacesChannel implements IServerChannel { return this.service.createUntitledWorkspace(folders); } + case 'deleteUntitledWorkspace': { + const w: IWorkspaceIdentifier = arg; + return this.service.deleteUntitledWorkspace({ id: w.id, configPath: URI.revive(w.configPath) }); + } } throw new Error(`Call not found: ${command}`); @@ -47,4 +51,8 @@ export class WorkspacesChannelClient implements IWorkspacesService { createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[]): Promise { return this.channel.call('createUntitledWorkspace', folders).then(reviveWorkspaceIdentifier); } + + deleteUntitledWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise { + return this.channel.call('deleteUntitledWorkspace', workspaceIdentifier); + } } diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 95a46d91ff0..272b810d1bf 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -7,12 +7,11 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'vs/base/common/path'; -import * as extfs from 'vs/base/node/extfs'; import * as pfs from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; import { WorkspacesMainService, IStoredWorkspace } from 'vs/platform/workspaces/electron-main/workspacesMainService'; -import { WORKSPACE_EXTENSION, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import { WORKSPACE_EXTENSION, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder, rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/common/workspaces'; import { NullLogService } from 'vs/platform/log/common/log'; import { URI } from 'vs/base/common/uri'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; @@ -233,95 +232,85 @@ suite('WorkspacesMainService', () => { }); }); - test('saveWorkspace (untitled)', () => { - return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { - const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); + test('rewriteWorkspaceFileForNewLocation', () => { + const folder1 = process.cwd(); // absolute path because outside of tmpDir + const tmpDir = os.tmpdir(); + const tmpInsideDir = path.join(os.tmpdir(), 'inside'); - return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => { - assert.ok(savedWorkspace.id); - assert.notEqual(savedWorkspace.id, workspace.id); - assertPathEquals(savedWorkspace.configPath.fsPath, workspaceConfigPath); + return createWorkspace([folder1, tmpInsideDir, path.join(tmpInsideDir, 'somefolder')]).then(workspace => { + const origContent = fs.readFileSync(workspace.configPath.fsPath).toString(); - const ws = JSON.parse(fs.readFileSync(savedWorkspace.configPath.fsPath).toString()) as IStoredWorkspace; - assert.equal(ws.folders.length, 3); - assertPathEquals((ws.folders[0]).path, process.cwd()); // absolute - assertPathEquals((ws.folders[1]).path, '.'); // relative - assertPathEquals((ws.folders[2]).path, path.relative(path.dirname(workspaceConfigPath), path.join(os.tmpdir(), 'somefolder'))); // relative + let origConfigPath = workspace.configPath; + let workspaceConfigPath = URI.file(path.join(tmpDir, 'inside', 'myworkspace1.code-workspace')); + let newContent = rewriteWorkspaceFileForNewLocation(origContent, origConfigPath, workspaceConfigPath); - extfs.delSync(workspaceConfigPath); - }); + let ws = JSON.parse(newContent) as IStoredWorkspace; + assert.equal(ws.folders.length, 3); + assertPathEquals((ws.folders[0]).path, folder1); // absolute path because outside of tmpdir + assertPathEquals((ws.folders[1]).path, '.'); + assertPathEquals((ws.folders[2]).path, 'somefolder'); + + origConfigPath = workspaceConfigPath; + workspaceConfigPath = URI.file(path.join(tmpDir, 'myworkspace2.code-workspace')); + newContent = rewriteWorkspaceFileForNewLocation(newContent, origConfigPath, workspaceConfigPath); + + ws = JSON.parse(newContent) as IStoredWorkspace; + assert.equal(ws.folders.length, 3); + assertPathEquals((ws.folders[0]).path, folder1); + assertPathEquals((ws.folders[1]).path, 'inside'); + assertPathEquals((ws.folders[2]).path, isWindows ? 'inside\\somefolder' : 'inside/somefolder'); + + origConfigPath = workspaceConfigPath; + workspaceConfigPath = URI.file(path.join(tmpDir, 'other', 'myworkspace2.code-workspace')); + newContent = rewriteWorkspaceFileForNewLocation(newContent, origConfigPath, workspaceConfigPath); + + ws = JSON.parse(newContent) as IStoredWorkspace; + assert.equal(ws.folders.length, 3); + assertPathEquals((ws.folders[0]).path, folder1); + assertPathEquals((ws.folders[1]).path, tmpInsideDir); + assertPathEquals((ws.folders[2]).path, path.join(tmpInsideDir, 'somefolder')); + + origConfigPath = workspaceConfigPath; + workspaceConfigPath = URI.parse('foo://foo/bar/myworkspace2.code-workspace'); + newContent = rewriteWorkspaceFileForNewLocation(newContent, origConfigPath, workspaceConfigPath); + + ws = JSON.parse(newContent) as IStoredWorkspace; + assert.equal(ws.folders.length, 3); + assert.equal((ws.folders[0]).uri, URI.file(folder1).toString(true)); + assert.equal((ws.folders[1]).uri, URI.file(tmpInsideDir).toString(true)); + assert.equal((ws.folders[2]).uri, URI.file(path.join(tmpInsideDir, 'somefolder')).toString(true)); + + service.deleteUntitledWorkspaceSync(workspace); }); }); - test('saveWorkspace (saved workspace)', () => { + test('rewriteWorkspaceFileForNewLocation (preserves comments)', () => { return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { - const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); - const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); + const workspaceConfigPath = URI.file(path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`)); - return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => { - return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => { - assert.ok(newSavedWorkspace.id); - assert.notEqual(newSavedWorkspace.id, workspace.id); - assertPathEquals(newSavedWorkspace.configPath.fsPath, newWorkspaceConfigPath); + let origContent = fs.readFileSync(workspace.configPath.fsPath).toString(); + origContent = `// this is a comment\n${origContent}`; - const ws = JSON.parse(fs.readFileSync(newSavedWorkspace.configPath.fsPath).toString()) as IStoredWorkspace; - assert.equal(ws.folders.length, 3); - assertPathEquals((ws.folders[0]).path, process.cwd()); // absolute path because outside of tmpdir - assertPathEquals((ws.folders[1]).path, '.'); // relative path because inside of tmpdir - assertPathEquals((ws.folders[2]).path, 'somefolder'); // relative + let newContent = rewriteWorkspaceFileForNewLocation(origContent, workspace.configPath, workspaceConfigPath); - extfs.delSync(workspaceConfigPath); - extfs.delSync(newWorkspaceConfigPath); - }); - }); + assert.equal(0, newContent.indexOf('// this is a comment')); + + service.deleteUntitledWorkspaceSync(workspace); }); }); - test('saveWorkspace (saved workspace, preserves comments)', () => { + test('rewriteWorkspaceFileForNewLocation (preserves forward slashes)', () => { return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { - const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); - const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); + const workspaceConfigPath = URI.file(path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`)); + let origContent = fs.readFileSync(workspace.configPath.fsPath).toString(); + origContent = origContent.replace(/[\\]/g, '/'); // convert backslash to slash - return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => { - const contents = fs.readFileSync(savedWorkspace.configPath.fsPath).toString(); - fs.writeFileSync(savedWorkspace.configPath.fsPath, `// this is a comment\n${contents}`); + const newContent = rewriteWorkspaceFileForNewLocation(origContent, workspace.configPath, workspaceConfigPath); - return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => { - assert.ok(newSavedWorkspace.id); - assert.notEqual(newSavedWorkspace.id, workspace.id); - assertPathEquals(newSavedWorkspace.configPath.fsPath, newWorkspaceConfigPath); + const ws = JSON.parse(newContent) as IStoredWorkspace; + assert.ok(ws.folders.every(f => (f).path.indexOf('\\') < 0)); - const savedContents = fs.readFileSync(newSavedWorkspace.configPath.fsPath).toString(); - assert.equal(0, savedContents.indexOf('// this is a comment')); - - extfs.delSync(workspaceConfigPath); - extfs.delSync(newWorkspaceConfigPath); - }); - }); - }); - }); - - test('saveWorkspace (saved workspace, preserves forward slashes)', () => { - return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { - const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); - const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); - - return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => { - const contents = fs.readFileSync(savedWorkspace.configPath.fsPath).toString(); - fs.writeFileSync(savedWorkspace.configPath.fsPath, contents.replace(/[\\]/g, '/')); // convert backslash to slash - - return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => { - assert.ok(newSavedWorkspace.id); - assert.notEqual(newSavedWorkspace.id, workspace.id); - assertPathEquals(newSavedWorkspace.configPath.fsPath, newWorkspaceConfigPath); - - const ws = JSON.parse(fs.readFileSync(newSavedWorkspace.configPath.fsPath).toString()) as IStoredWorkspace; - assert.ok(ws.folders.every(f => (f).path.indexOf('\\') < 0)); - - extfs.delSync(workspaceConfigPath); - extfs.delSync(newWorkspaceConfigPath); - }); - }); + service.deleteUntitledWorkspaceSync(workspace); }); }); @@ -337,15 +326,7 @@ suite('WorkspacesMainService', () => { test('deleteUntitledWorkspaceSync (saved)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { - const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); - - return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => { - assert.ok(fs.existsSync(savedWorkspace.configPath.fsPath)); - - service.deleteUntitledWorkspaceSync(savedWorkspace); - - assert.ok(fs.existsSync(savedWorkspace.configPath.fsPath)); - }); + service.deleteUntitledWorkspaceSync(workspace); }); }); diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 5897ab9e710..14c2f2f4fe6 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -180,7 +180,7 @@ export class ResourcesDropHandler { // Add external ones to recently open list unless dropped resource is a workspace const filesToAddToHistory = untitledOrFileResources.filter(d => d.isExternal && d.resource.scheme === Schemas.file).map(d => d.resource); if (filesToAddToHistory.length) { - this.windowsService.addRecentlyOpened(filesToAddToHistory); + this.windowsService.addRecentlyOpened([], [], filesToAddToHistory); } const editors: IResourceEditor[] = untitledOrFileResources.map(untitledOrFileResource => ({ diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index e65b8e1c29e..c1656dab17f 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -51,4 +51,9 @@ export interface IWorkspaceEditingService { * copies current workspace settings to the target workspace. */ copyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): Promise; + + /** + * picks a new workspace path + */ + pickNewWorkspacePath(): Promise; } \ No newline at end of file diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index c91fa335414..5fcaa129676 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -9,7 +9,7 @@ import * as nls from 'vs/nls'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWindowService, MessageBoxOptions, IWindowsService } from 'vs/platform/windows/common/windows'; import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing'; -import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, isWorkspaceIdentifier, toWorkspaceIdentifier, IWorkspacesService, rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesService, rewriteWorkspaceFileForNewLocation, WORKSPACE_FILTER } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -21,11 +21,14 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { distinct } from 'vs/base/common/arrays'; -import { isLinux } from 'vs/base/common/platform'; -import { isEqual, basename } from 'vs/base/common/resources'; +import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform'; +import { isEqual, basename, isEqualOrParent } from 'vs/base/common/resources'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IFileService } from 'vs/platform/files/common/files'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; +import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { mnemonicButtonLabel } from 'vs/base/common/labels'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -44,8 +47,97 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { @IFileService private readonly fileSystemService: IFileService, @IWindowsService private readonly windowsService: IWindowsService, @IWorkspacesService private readonly workspaceService: IWorkspacesService, - @IEnvironmentService private readonly environmentService: IEnvironmentService + @IEnvironmentService private readonly environmentService: IEnvironmentService, + @IFileDialogService private readonly fileDialogService: IFileDialogService, + @IDialogService private readonly dialogService: IDialogService, + @ILifecycleService readonly lifecycleService: ILifecycleService ) { + + lifecycleService.onBeforeShutdown(async e => { + const saveOperation = this.saveUntitedBeforeShutdown(e.reason); + if (saveOperation) { + e.veto(saveOperation); + } + }); + + } + + private saveUntitedBeforeShutdown(reason: ShutdownReason): Promise | undefined { + if (reason === ShutdownReason.RELOAD || reason === ShutdownReason.QUIT) { + return undefined; + } + const workspaceIdentifier = this.getCurrentWorkspaceIdentifier(); + if (!workspaceIdentifier) { + return undefined; // not a workspace + } + if (!isEqualOrParent(workspaceIdentifier.configPath, this.environmentService.untitledWorkspacesHome)) { + return undefined; // not an untitled workspace + } + + return this.windowsService.getWindowCount().then(windowCount => { + if (reason === ShutdownReason.CLOSE && !isMacintosh && windowCount === 1) { + return false; // Windows/Linux: quits when last window is closed, so do not ask then + } + enum ConfirmResult { + SAVE, + DONT_SAVE, + CANCEL + } + + const save = { label: mnemonicButtonLabel(nls.localize('save', "Save")), result: ConfirmResult.SAVE }; + const dontSave = { label: mnemonicButtonLabel(nls.localize('doNotSave', "Don't Save")), result: ConfirmResult.DONT_SAVE }; + const cancel = { label: nls.localize('cancel', "Cancel"), result: ConfirmResult.CANCEL }; + + const buttons: { label: string; result: ConfirmResult; }[] = []; + if (isWindows) { + buttons.push(save, dontSave, cancel); + } else if (isLinux) { + buttons.push(dontSave, cancel, save); + } else { + buttons.push(save, cancel, dontSave); + } + + const message = nls.localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"); + const detail = nls.localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."); + const cancelId = buttons.indexOf(cancel); + + return this.dialogService.show(Severity.Warning, message, buttons.map(button => button.label), { detail, cancelId }).then(res => { + switch (buttons[res].result) { + + // Cancel: veto unload + case ConfirmResult.CANCEL: + return true; + + // Don't Save: delete workspace + case ConfirmResult.DONT_SAVE: + this.workspaceService.deleteUntitledWorkspace(workspaceIdentifier); + return false; + + // Save: save workspace, but do not veto unload + case ConfirmResult.SAVE: { + return this.pickNewWorkspacePath().then(newWorkspacePath => { + if (newWorkspacePath) { + return this.saveWorkspaceAs(workspaceIdentifier, newWorkspacePath).then(_ => { + this.windowsService.addRecentlyOpened([newWorkspacePath], [], []); + this.workspaceService.deleteUntitledWorkspace(workspaceIdentifier); + return false; + }, () => false); + } + return true; // keep veto if no target was provided + }); + } + } + }); + }); + } + + pickNewWorkspacePath(): Promise { + return this.fileDialogService.showSaveDialog({ + saveLabel: mnemonicButtonLabel(nls.localize('save', "Save")), + title: nls.localize('saveWorkspace', "Save Workspace"), + filters: WORKSPACE_FILTER, + defaultUri: this.fileDialogService.defaultWorkspacePath() + }); } updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise { @@ -164,11 +256,11 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { if (!this.isValidTargetWorkspacePath(path)) { return Promise.reject(null); } - const currentWorkspaceIdentifier = toWorkspaceIdentifier(this.contextService.getWorkspace()); - if (!isWorkspaceIdentifier(currentWorkspaceIdentifier)) { + const workspaceIdentifier = this.getCurrentWorkspaceIdentifier(); + if (!workspaceIdentifier) { return Promise.reject(null); } - await this.saveWorkspaceAs(currentWorkspaceIdentifier, path); + await this.saveWorkspaceAs(workspaceIdentifier, path); return this.enterWorkspace(path); } @@ -328,4 +420,12 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { return this.jsonEditingService.write(toWorkspace.configPath, { key: 'settings', value: targetWorkspaceConfiguration }, true); } + + private getCurrentWorkspaceIdentifier(): IWorkspaceIdentifier | undefined { + const workspace = this.contextService.getWorkspace(); + if (workspace && workspace.configuration) { + return { id: workspace.id, configPath: workspace.configuration }; + } + return undefined; + } } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index d605a994a11..2b7d37ffe8c 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1242,7 +1242,7 @@ export class TestWindowsService implements IWindowsService { return Promise.resolve(); } - addRecentlyOpened(_files: URI[]): Promise { + addRecentlyOpened(_workspaces: URI[], _folders: URI[], _files: URI[]): Promise { return Promise.resolve(); } From cb78f9448c294da85bf8499d07235e807ddf3104 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 27 Feb 2019 14:53:54 +0100 Subject: [PATCH 008/172] polish --- src/vs/code/electron-main/windows.ts | 23 +------------------ .../browser/actions/workspaceActions.ts | 18 +++------------ .../workspace/node/workspaceEditingService.ts | 11 ++++----- 3 files changed, 8 insertions(+), 44 deletions(-) diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 2e94e6cfaed..4f9dfee68b6 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -15,7 +15,7 @@ import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; import { hasArgs, asArray } from 'vs/platform/environment/node/argv'; import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences } from 'electron'; import { parseLineAndColumnAware } from 'vs/code/node/paths'; -import { ILifecycleService, UnloadReason, IWindowUnloadEvent, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; +import { ILifecycleService, UnloadReason, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, IPathsToWaitFor, IEnterWorkspaceResult, IMessageBoxResult, INewWindowOptions, IURIToOpen, URIType, OpenDialogOptions } from 'vs/platform/windows/common/windows'; @@ -233,7 +233,6 @@ export class WindowsManager implements IWindowsMainService { } // Handle various lifecycle events around windows - this.lifecycleService.onBeforeWindowUnload(e => this.onBeforeWindowUnload(e)); this.lifecycleService.onBeforeWindowClose(window => this.onBeforeWindowClose(window)); this.lifecycleService.onBeforeShutdown(() => this.onBeforeShutdown()); this.onWindowsCountChanged(e => { @@ -1526,26 +1525,6 @@ export class WindowsManager implements IWindowsMainService { this.workspacesManager.pickWorkspaceAndOpen(options); } - private onBeforeWindowUnload(e: IWindowUnloadEvent): void { - const windowClosing = (e.reason === UnloadReason.CLOSE); - const windowLoading = (e.reason === UnloadReason.LOAD); - if (!windowClosing && !windowLoading) { - return; // only interested when window is closing or loading - } - - const workspace = e.window.openedWorkspace; - if (!workspace || !this.workspacesMainService.isUntitledWorkspace(workspace)) { - return; // only care about untitled workspaces to ask for saving - } - - if (e.window.config && !!e.window.config.extensionDevelopmentPath) { - // do not ask to save workspace when doing extension development - // but still delete it. - this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); - return; - } - } - 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 4520821cde9..96ba6f2f22c 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -9,12 +9,10 @@ import { IWindowService } from 'vs/platform/windows/common/windows'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; -import { WORKSPACE_FILTER, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; -import { mnemonicButtonLabel } from 'vs/base/common/labels'; +import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; -import { URI } from 'vs/base/common/uri'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -132,15 +130,14 @@ export class SaveWorkspaceAsAction extends Action { id: string, label: string, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService, - @IFileDialogService private readonly dialogService: IFileDialogService + @IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService ) { super(id, label); } run(): Promise { - return this.getNewWorkspaceConfigPath().then((configPathUri): Promise | void => { + return this.workspaceEditingService.pickNewWorkspacePath().then((configPathUri): Promise | void => { if (configPathUri) { switch (this.contextService.getWorkbenchState()) { case WorkbenchState.EMPTY: @@ -154,15 +151,6 @@ export class SaveWorkspaceAsAction extends Action { } }); } - - private getNewWorkspaceConfigPath(): Promise { - return this.dialogService.showSaveDialog({ - saveLabel: mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), - title: nls.localize('saveWorkspace', "Save Workspace"), - filters: WORKSPACE_FILTER, - defaultUri: this.dialogService.defaultWorkspacePath() - }); - } } export class OpenWorkspaceAction extends Action { diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index 5fcaa129676..1003e3f040f 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -63,15 +63,12 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { } private saveUntitedBeforeShutdown(reason: ShutdownReason): Promise | undefined { - if (reason === ShutdownReason.RELOAD || reason === ShutdownReason.QUIT) { - return undefined; + if (reason !== ShutdownReason.LOAD && reason !== ShutdownReason.CLOSE) { + return undefined; // only interested when window is closing or loading } const workspaceIdentifier = this.getCurrentWorkspaceIdentifier(); - if (!workspaceIdentifier) { - return undefined; // not a workspace - } - if (!isEqualOrParent(workspaceIdentifier.configPath, this.environmentService.untitledWorkspacesHome)) { - return undefined; // not an untitled workspace + if (!workspaceIdentifier || !isEqualOrParent(workspaceIdentifier.configPath, this.environmentService.untitledWorkspacesHome)) { + return undefined; // only care about untitled workspaces to ask for saving } return this.windowsService.getWindowCount().then(windowCount => { From 02ca5bde963ff890433427da44c630d8379014fb Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 2 Mar 2019 19:09:32 +0900 Subject: [PATCH 009/172] Make an error message easier to understand --- build/gulpfile.hygiene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 1af30179a06..9ec4d5ef336 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -228,7 +228,7 @@ function hygiene(some) { let formatted = result.dest.replace(/\r\n/gm, '\n'); if (original !== formatted) { - console.error('File not formatted:', file.relative); + console.error('File not formatted with tsfmt:', file.relative); errorCount++; } cb(null, file); From 0e5614f00287597620702a570441ec8da3613d99 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 5 Mar 2019 08:44:13 +0900 Subject: [PATCH 010/172] change the message to clarify the intention. --- build/gulpfile.hygiene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 9ec4d5ef336..187968a95bc 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -228,7 +228,7 @@ function hygiene(some) { let formatted = result.dest.replace(/\r\n/gm, '\n'); if (original !== formatted) { - console.error('File not formatted with tsfmt:', file.relative); + console.error("File not formatted. Run the 'Format Document' command to fix it:", file.relative); errorCount++; } cb(null, file); From fe169ce4d28fde2a8f71c2d8600c4780b6457e46 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 16:46:45 -0800 Subject: [PATCH 011/172] Move terminalLinkHandler, electron-browser->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- .../terminalLinkHandler.ts | 58 +++++++++++++++++-- .../electron-browser/terminalInstance.ts | 2 +- .../terminalLinkHandler.test.ts | 16 ++--- 4 files changed, 62 insertions(+), 16 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/terminalLinkHandler.ts (87%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 7802f41674b..c6deb24a509 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -279,6 +279,7 @@ "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", + "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", "./vs/workbench/contrib/terminal/browser/terminalTab.ts", "./vs/workbench/contrib/terminal/browser/terminalWidgetManager.ts", @@ -290,7 +291,6 @@ "./vs/workbench/contrib/terminal/electron-browser/terminalActions.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler.ts b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts similarity index 87% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler.ts rename to src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts index 734d13fd45a..d0c1214879c 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts @@ -6,8 +6,7 @@ import * as nls from 'vs/nls'; import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; -import * as pfs from 'vs/base/node/pfs'; -import { URI as Uri } from 'vs/base/common/uri'; +import { URI } from 'vs/base/common/uri'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager'; @@ -15,7 +14,53 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ITerminalService } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { ILinkMatcherOptions } from 'vscode-xterm'; +import { IFileService } from 'vs/platform/files/common/files'; + +// Since importing from vscode-xterm would be a layer breakage here the type is copied inline +// import { ILinkMatcherOptions } from 'vscode-xterm'; + +/** + * An object containing options for a link matcher. + */ +export interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + + /** + * A callback that validates whether to create an individual link, pass + * whether the link is valid to the callback. + */ + validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; + + /** + * A callback that fires when the mouse hovers over a link for a moment. + */ + tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; + + /** + * A callback that fires when the mouse leaves a link. Note that this can + * happen even when tooltipCallback hasn't fired for the link yet. + */ + leaveCallback?: (event: MouseEvent, uri: string) => boolean | void; + + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; + + /** + * A callback that fires when the mousedown and click events occur that + * determines whether a link will be activated upon click. This enables + * only activating a link when a certain modifier is held down, if not the + * mouse event will continue propagation (eg. double click to select word). + */ + willLinkActivate?: (event: MouseEvent, uri: string) => boolean; +} const pathPrefix = '(\\.\\.?|\\~)'; const pathSeparatorClause = '\\/'; @@ -74,6 +119,7 @@ export class TerminalLinkHandler { @IEditorService private readonly _editorService: IEditorService, @IConfigurationService private readonly _configurationService: IConfigurationService, @ITerminalService private readonly _terminalService: ITerminalService, + @IFileService private readonly _fileService: IFileService ) { const baseLocalLinkClause = _platform === platform.Platform.Windows ? winLocalLinkClause : unixLocalLinkClause; // Append line and column number regex @@ -203,7 +249,7 @@ export class TerminalLinkHandler { if (!normalizedUrl) { return Promise.resolve(null); } - const resource = Uri.file(normalizedUrl); + const resource = URI.file(normalizedUrl); const lineColumnInfo: LineColumnInfo = this.extractLineColumnInfo(link); const selection: ITextEditorSelection = { startLineNumber: lineColumnInfo.lineNumber, @@ -223,7 +269,7 @@ export class TerminalLinkHandler { } private _handleHypertextLink(url: string): void { - const uri = Uri.parse(url); + const uri = URI.parse(url); this._openerService.open(uri); } @@ -288,7 +334,7 @@ export class TerminalLinkHandler { } // Ensure the file exists on disk, so an editor can be opened after clicking it - return pfs.fileExists(linkUrl).then(isFile => { + return this._fileService.existsFile(URI.file(linkUrl)).then(isFile => { if (!isFile) { return null; } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index f3764101c3a..22f9378da7b 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -31,7 +31,7 @@ import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalPr import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; -import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler'; +import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/electron-browser/terminalProcessManager'; import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/node/terminalCommandTracker'; import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts index 99edaab4671..5b708d68123 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { Platform } from 'vs/base/common/platform'; -import { TerminalLinkHandler, LineColumnInfo } from 'vs/workbench/contrib/terminal/electron-browser/terminalLinkHandler'; +import { TerminalLinkHandler, LineColumnInfo } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; import * as strings from 'vs/base/common/strings'; import * as path from 'vs/base/common/path'; import * as sinon from 'sinon'; @@ -39,7 +39,7 @@ interface LinkFormatInfo { suite('Workbench - TerminalLinkHandler', () => { suite('localLinkRegex', () => { test('Windows', () => { - const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!); + const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!, null!); function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) { assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl); assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl); @@ -111,7 +111,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('Linux', () => { - const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!); + const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!, null!); function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) { assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl); assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl); @@ -175,7 +175,7 @@ suite('Workbench - TerminalLinkHandler', () => { suite('preprocessPath', () => { test('Windows', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!, null!); linkHandler.processCwd = 'C:\\base'; let stub = sinon.stub(path, 'join', function (arg1: string, arg2: string) { @@ -188,7 +188,7 @@ suite('Workbench - TerminalLinkHandler', () => { stub.restore(); }); test('Windows - spaces', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null!, null!, null!, null!, null!); linkHandler.processCwd = 'C:\\base dir'; let stub = sinon.stub(path, 'join', function (arg1: string, arg2: string) { @@ -202,7 +202,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('Linux', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!, null!); linkHandler.processCwd = '/base'; let stub = sinon.stub(path, 'join', function (arg1: string, arg2: string) { @@ -216,7 +216,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('No Workspace', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!, null!); assert.equal(linkHandler.preprocessPath('./src/file1'), null); assert.equal(linkHandler.preprocessPath('src/file2'), null); @@ -226,7 +226,7 @@ suite('Workbench - TerminalLinkHandler', () => { test('gitDiffLinkRegex', () => { // The platform is irrelevant because the links generated by Git are the same format regardless of platform - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!, null!); function assertAreGoodMatches(matches: RegExpMatchArray | null) { if (matches) { From 5d2a154da6e3c0f0e019b91b0e02e17beac74995 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 16:56:26 -0800 Subject: [PATCH 012/172] Add terminal-specific tslint rule to allow vscode-xterm imports --- .../terminal/browser/terminalLinkHandler.ts | 47 +------------------ tslint.json | 7 +++ 2 files changed, 8 insertions(+), 46 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts index d0c1214879c..0c7246a7038 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts @@ -15,52 +15,7 @@ import { ITerminalService } from 'vs/workbench/contrib/terminal/common/terminal' import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IFileService } from 'vs/platform/files/common/files'; - -// Since importing from vscode-xterm would be a layer breakage here the type is copied inline -// import { ILinkMatcherOptions } from 'vscode-xterm'; - -/** - * An object containing options for a link matcher. - */ -export interface ILinkMatcherOptions { - /** - * The index of the link from the regex.match(text) call. This defaults to 0 - * (for regular expressions without capture groups). - */ - matchIndex?: number; - - /** - * A callback that validates whether to create an individual link, pass - * whether the link is valid to the callback. - */ - validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; - - /** - * A callback that fires when the mouse hovers over a link for a moment. - */ - tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; - - /** - * A callback that fires when the mouse leaves a link. Note that this can - * happen even when tooltipCallback hasn't fired for the link yet. - */ - leaveCallback?: (event: MouseEvent, uri: string) => boolean | void; - - /** - * The priority of the link matcher, this defines the order in which the link - * matcher is evaluated relative to others, from highest to lowest. The - * default value is 0. - */ - priority?: number; - - /** - * A callback that fires when the mousedown and click events occur that - * determines whether a link will be activated upon click. This enables - * only activating a link when a certain modifier is held down, if not the - * mouse event will continue propagation (eg. double click to select word). - */ - willLinkActivate?: (event: MouseEvent, uri: string) => boolean; -} +import { ILinkMatcherOptions } from 'vscode-xterm'; const pathPrefix = '(\\.\\.?|\\~)'; const pathSeparatorClause = '\\/'; diff --git a/tslint.json b/tslint.json index 0383001a61b..5365738399a 100644 --- a/tslint.json +++ b/tslint.json @@ -485,6 +485,13 @@ "assert" ] }, + { + "target": "**/vs/workbench/contrib/terminal/browser/**", + "restrictions": [ + "vscode-xterm", + "**/vs/**" + ] + }, { "target": "**/vs/code/node/**", "restrictions": [ From 8afa7773d5237bcfd8602d6afb2f5a92c6c21b57 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:16:21 -0800 Subject: [PATCH 013/172] Remove os dep in terminalEnvironment --- .../api/node/extHostTerminalService.ts | 3 ++- .../terminal/browser/terminalService.ts | 25 +++++++++++++++++++ .../terminal/common/terminalService.ts | 9 +++++-- .../terminalProcessManager.ts | 4 ++- .../electron-browser/terminalService.ts | 13 ++-------- .../terminal/node/terminalEnvironment.ts | 5 ++-- .../test/node/terminalEnvironment.test.ts | 23 ++++++++--------- 7 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/browser/terminalService.ts diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 4e10c68feb2..156d7ad5c82 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as os from 'os'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as platform from 'vs/base/common/platform'; import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; @@ -429,7 +430,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { // TODO: @daniel const activeWorkspaceRootUri = URI.revive(activeWorkspaceRootUriComponents); - const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, activeWorkspaceRootUri, terminalConfig.cwd); + const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, os.homedir(), activeWorkspaceRootUri, terminalConfig.cwd); // TODO: Pull in and resolve config settings // // Resolve env vars from config and shell diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts new file mode 100644 index 00000000000..060ce2863aa --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITerminalService } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalService as CommonTerminalService } from 'vs/workbench/contrib/terminal/common/terminalService'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IStorageService } from 'vs/platform/storage/common/storage'; + +export abstract class TerminalService extends CommonTerminalService implements ITerminalService { + + constructor( + @IContextKeyService contextKeyService: IContextKeyService, + @IPanelService panelService: IPanelService, + @IPartService partService: IPartService, + @ILifecycleService lifecycleService: ILifecycleService, + @IStorageService storageService: IStorageService + ) { + super(contextKeyService, panelService, partService, lifecycleService, storageService); + } +} \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 2af5a375481..ab3e50b1885 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -21,7 +21,9 @@ export abstract class TerminalService implements ITerminalService { protected _findWidgetVisible: IContextKey; protected _terminalContainer: HTMLElement; protected _terminalTabs: ITerminalTab[]; - protected abstract _terminalInstances: ITerminalInstance[]; + protected get _terminalInstances(): ITerminalInstance[] { + return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), []); + } private _findState: FindReplaceState; private _activeTabIndex: number; @@ -89,13 +91,16 @@ export abstract class TerminalService implements ITerminalService { protected abstract _showTerminalCloseConfirmation(): Promise; protected abstract _showNotEnoughSpaceToast(): void; public abstract createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; - public abstract createTerminalRenderer(name: string): ITerminalInstance; public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; public abstract getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): Promise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; public abstract requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void; + public createTerminalRenderer(name: string): ITerminalInstance { + return this.createTerminal({ name, isRendererOnly: true }); + } + private _onBeforeShutdown(): boolean | Promise { if (this.terminalInstances.length === 0) { // No terminal instances, don't veto diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts index a3fa9af9e3d..786c7f7f2f8 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts @@ -21,6 +21,7 @@ import { Schemas } from 'vs/base/common/network'; import { REMOTE_HOST_SCHEME, getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; import { sanitizeProcessEnvironment } from 'vs/base/node/processes'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -61,6 +62,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWindowService private readonly _windowService: IWindowService, @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, + @IEnvironmentService private readonly _environmentSertvice: IEnvironmentService ) { this.ptyProcessReady = new Promise(c => { this.onProcessReady(() => { @@ -110,7 +112,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { } const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); - const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, activeWorkspaceRootUri, this._configHelper.config.cwd); + const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentSertvice.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd); // Compel type system as process.env should not have any undefined entries let env: platform.IProcessEnvironment = {}; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index fbace8ec6fb..f916502d8f5 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -13,7 +13,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; -import { TerminalService as AbstractTerminalService } from 'vs/workbench/contrib/terminal/common/terminalService'; +import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -30,15 +30,10 @@ import { URI } from 'vs/base/common/uri'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { coalesce } from 'vs/base/common/arrays'; -export class TerminalService extends AbstractTerminalService implements ITerminalService { +export class TerminalService extends BrowserTerminalService implements ITerminalService { private _configHelper: TerminalConfigHelper; public get configHelper(): ITerminalConfigHelper { return this._configHelper; } - protected _terminalTabs: TerminalTab[]; - protected get _terminalInstances(): ITerminalInstance[] { - return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), []); - } - constructor( @IContextKeyService contextKeyService: IContextKeyService, @IPanelService panelService: IPanelService, @@ -98,10 +93,6 @@ export class TerminalService extends AbstractTerminalService implements ITermina return instance; } - public createTerminalRenderer(name: string): ITerminalInstance { - return this.createTerminal({ name, isRendererOnly: true }); - } - public createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance { const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig); this._onInstanceCreated.fire(instance); diff --git a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts index 612ea746d21..668ec2ef2ac 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; import pkg from 'vs/platform/product/node/package'; @@ -102,7 +101,7 @@ function _getLangEnvVariable(locale?: string) { return parts.join('_') + '.UTF-8'; } -export function getCwd(shell: IShellLaunchConfig, root?: Uri, customCwd?: string): string { +export function getCwd(shell: IShellLaunchConfig, userHome: string, root?: Uri, customCwd?: string): string { if (shell.cwd) { return (typeof shell.cwd === 'object') ? shell.cwd.fsPath : shell.cwd; } @@ -120,7 +119,7 @@ export function getCwd(shell: IShellLaunchConfig, root?: Uri, customCwd?: string // If there was no custom cwd or it was relative with no workspace if (!cwd) { - cwd = root ? root.fsPath : os.homedir(); + cwd = root ? root.fsPath : userHome; } return _sanitizeCwd(cwd); diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts index 0f9ecc1299a..1549d0b2e56 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as os from 'os'; import * as platform from 'vs/base/common/platform'; import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; import { URI as Uri } from 'vs/base/common/uri'; @@ -101,32 +100,32 @@ suite('Workbench - TerminalEnvironment', () => { assert.equal(Uri.file(a).fsPath, Uri.file(b).fsPath); } - test('should default to os.homedir() for an empty workspace', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, undefined, undefined), os.homedir()); + test('should default to userHome for an empty workspace', () => { + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, undefined), '/userHome/'); }); test('should use to the workspace if it exists', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, Uri.file('/foo'), undefined), '/foo'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', Uri.file('/foo'), undefined), '/foo'); }); test('should use an absolute custom cwd as is', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, undefined, '/foo'), '/foo'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, '/foo'), '/foo'); }); test('should normalize a relative custom cwd against the workspace path', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, Uri.file('/bar'), 'foo'), '/bar/foo'); - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, Uri.file('/bar'), './foo'), '/bar/foo'); - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, Uri.file('/bar'), '../foo'), '/foo'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', Uri.file('/bar'), 'foo'), '/bar/foo'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', Uri.file('/bar'), './foo'), '/bar/foo'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', Uri.file('/bar'), '../foo'), '/foo'); }); test('should fall back for relative a custom cwd that doesn\'t have a workspace', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, undefined, 'foo'), os.homedir()); - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, undefined, './foo'), os.homedir()); - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, undefined, '../foo'), os.homedir()); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, 'foo'), '/userHome/'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, './foo'), '/userHome/'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [] }, '/userHome/', undefined, '../foo'), '/userHome/'); }); test('should ignore custom cwd when told to ignore', () => { - assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, Uri.file('/bar'), '/foo'), '/bar'); + assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', Uri.file('/bar'), '/foo'), '/bar'); }); }); From badedf5d7d88fbb3adef5cd43c7a2cc9ad06a586 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:22:46 -0800 Subject: [PATCH 014/172] Move terminalEnvironment, node->common Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- src/vs/workbench/api/node/extHostTerminalService.ts | 5 +++-- .../terminal/{node => common}/terminalEnvironment.ts | 5 ++--- .../terminal/electron-browser/terminalPanel.ts | 2 +- .../electron-browser/terminalProcessManager.ts | 10 ++++++---- .../terminal/test/node/terminalEnvironment.test.ts | 12 ++++++------ 6 files changed, 19 insertions(+), 17 deletions(-) rename src/vs/workbench/contrib/terminal/{node => common}/terminalEnvironment.ts (96%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 7412a04e395..6d5d4e9b370 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -286,6 +286,7 @@ "./vs/workbench/contrib/terminal/common/terminal.ts", "./vs/workbench/contrib/terminal/common/terminalColorRegistry.ts", "./vs/workbench/contrib/terminal/common/terminalCommands.ts", + "./vs/workbench/contrib/terminal/common/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalActions.ts", @@ -295,7 +296,6 @@ "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalCommandTracker.ts", - "./vs/workbench/contrib/terminal/node/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", "./vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 156d7ad5c82..6f80fc77c38 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -4,10 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import pkg from 'vs/platform/product/node/package'; import * as os from 'os'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as platform from 'vs/base/common/platform'; -import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; +import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { Event, Emitter } from 'vs/base/common/event'; import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; @@ -451,7 +452,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { // Continue env initialization, merging in the env from the launch // config and adding keys that are needed to create the process - terminalEnvironment.addTerminalEnvironmentKeys(env, platform.locale, terminalConfig.get('setLocaleVariables')); + terminalEnvironment.addTerminalEnvironmentKeys(env, pkg.version, platform.locale, terminalConfig.get('setLocaleVariables')); // Fork the process and listen for messages this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env); diff --git a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts similarity index 96% rename from src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts rename to src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index 668ec2ef2ac..cf8e7fab850 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -5,7 +5,6 @@ import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; -import pkg from 'vs/platform/product/node/package'; import { URI as Uri } from 'vs/base/common/uri'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IShellLaunchConfig, ITerminalEnvironment } from 'vs/workbench/contrib/terminal/common/terminal'; @@ -50,9 +49,9 @@ function _mergeEnvironmentValue(env: ITerminalEnvironment, key: string, value: s } } -export function addTerminalEnvironmentKeys(env: ITerminalEnvironment, locale: string | undefined, setLocaleVariables: boolean): void { +export function addTerminalEnvironmentKeys(env: ITerminalEnvironment, version: string | undefined, locale: string | undefined, setLocaleVariables: boolean): void { env['TERM_PROGRAM'] = 'vscode'; - env['TERM_PROGRAM_VERSION'] = pkg.version; + env['TERM_PROGRAM_VERSION'] = version ? version : null; if (setLocaleVariables) { env['LANG'] = _getLangEnvVariable(locale); } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts index b4e7019e896..7d301112c40 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts @@ -6,7 +6,7 @@ import * as dom from 'vs/base/browser/dom'; import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; -import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; +import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { Action, IAction } from 'vs/base/common/actions'; import { IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts index 786c7f7f2f8..0a9923779e8 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as platform from 'vs/base/common/platform'; -import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; +import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { ILogService } from 'vs/platform/log/common/log'; @@ -22,6 +22,7 @@ import { REMOTE_HOST_SCHEME, getRemoteAuthority } from 'vs/platform/remote/commo import { sanitizeProcessEnvironment } from 'vs/base/node/processes'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IProductService } from 'vs/platform/product/common/product'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -62,7 +63,8 @@ export class TerminalProcessManager implements ITerminalProcessManager { @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWindowService private readonly _windowService: IWindowService, @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, - @IEnvironmentService private readonly _environmentSertvice: IEnvironmentService + @IEnvironmentService private readonly _environmentService: IEnvironmentService, + @IProductService private readonly _productService: IProductService ) { this.ptyProcessReady = new Promise(c => { this.onProcessReady(() => { @@ -112,7 +114,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { } const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); - const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentSertvice.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd); + const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentService.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd); // Compel type system as process.env should not have any undefined entries let env: platform.IProcessEnvironment = {}; @@ -143,7 +145,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { sanitizeProcessEnvironment(env, 'VSCODE_IPC_HOOK_CLI'); // Adding other env keys necessary to create the process - terminalEnvironment.addTerminalEnvironmentKeys(env, platform.locale, this._configHelper.config.setLocaleVariables); + terminalEnvironment.addTerminalEnvironmentKeys(env, this._productService.version, platform.locale, this._configHelper.config.setLocaleVariables); } this._logService.debug(`Terminal process launching`, shellLaunchConfig, initialCwd, cols, rows, env); diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts index 1549d0b2e56..6153a741193 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import * as platform from 'vs/base/common/platform'; -import * as terminalEnvironment from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; +import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { URI as Uri } from 'vs/base/common/uri'; import { IStringDictionary } from 'vs/base/common/collections'; @@ -13,21 +13,21 @@ suite('Workbench - TerminalEnvironment', () => { test('addTerminalEnvironmentKeys', () => { const env = { FOO: 'bar' }; const locale = 'en-au'; - terminalEnvironment.addTerminalEnvironmentKeys(env, locale, true); + terminalEnvironment.addTerminalEnvironmentKeys(env, '1.2.3', locale, true); assert.equal(env['TERM_PROGRAM'], 'vscode'); - assert.equal(env['TERM_PROGRAM_VERSION'].search(/^\d+\.\d+\.\d+$/), 0); + assert.equal(env['TERM_PROGRAM_VERSION'], '1.2.3'); assert.equal(env['LANG'], 'en_AU.UTF-8', 'LANG is equal to the requested locale with UTF-8'); const env2 = { FOO: 'bar' }; - terminalEnvironment.addTerminalEnvironmentKeys(env2, undefined, true); + terminalEnvironment.addTerminalEnvironmentKeys(env2, '1.2.3', undefined, true); assert.equal(env2['LANG'], 'en_US.UTF-8', 'LANG is equal to en_US.UTF-8 as fallback.'); // More info on issue #14586 const env3 = { LANG: 'replace' }; - terminalEnvironment.addTerminalEnvironmentKeys(env3, undefined, true); + terminalEnvironment.addTerminalEnvironmentKeys(env3, '1.2.3', undefined, true); assert.equal(env3['LANG'], 'en_US.UTF-8', 'LANG is set to the fallback LANG'); const env4 = { LANG: 'en_US.UTF-8' }; - terminalEnvironment.addTerminalEnvironmentKeys(env3, undefined, true); + terminalEnvironment.addTerminalEnvironmentKeys(env3, '1.2.3', undefined, true); assert.equal(env4['LANG'], 'en_US.UTF-8', 'LANG is equal to the parent environment\'s LANG'); }); From 5b7bdaccdecbab4d19521369dc2d5f65cb094db4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:31:58 -0800 Subject: [PATCH 015/172] Move terminalActions, electron-browser->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- .../terminal/{electron-browser => browser}/terminalActions.ts | 4 ++-- .../terminal/electron-browser/terminal.contribution.ts | 2 +- .../contrib/terminal/electron-browser/terminalPanel.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/terminalActions.ts (99%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 6d5d4e9b370..19a576445ba 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -278,6 +278,7 @@ "./vs/workbench/contrib/surveys/electron-browser/languageSurveys.contribution.ts", "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", + "./vs/workbench/contrib/terminal/browser/terminalActions.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", @@ -289,7 +290,6 @@ "./vs/workbench/contrib/terminal/common/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalActions.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts similarity index 99% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalActions.ts rename to src/vs/workbench/contrib/terminal/browser/terminalActions.ts index a202076042b..ea11c54029c 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as os from 'os'; import { Action, IAction } from 'vs/base/common/actions'; import { EndOfLinePreference } from 'vs/editor/common/model'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; @@ -34,6 +33,7 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; +import { isWindows } from 'vs/base/common/platform'; export const TERMINAL_PICKER_PREFIX = 'term '; @@ -659,7 +659,7 @@ export class RunSelectedTextInTerminalAction extends Action { if (selection.isEmpty()) { text = editor.getModel().getLineContent(selection.selectionStartLineNumber).trim(); } else { - const endOfLinePreference = os.EOL === '\n' ? EndOfLinePreference.LF : EndOfLinePreference.CRLF; + const endOfLinePreference = isWindows ? EndOfLinePreference.LF : EndOfLinePreference.CRLF; text = editor.getModel().getValueInRange(selection, endOfLinePreference); } instance.sendText(text, true); diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index b15ee85b95b..562568064b1 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -16,7 +16,7 @@ import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KillTerminalAction, ClearSelectionTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, SplitInActiveWorkspaceTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction, ScrollToPreviousCommandAction, ScrollToNextCommandAction, SelectToPreviousCommandAction, SelectToNextCommandAction, SelectToPreviousLineAction, SelectToNextLineAction, ToggleEscapeSequenceLoggingAction, SendSequenceTerminalCommand, ToggleRegexCommand, ToggleWholeWordCommand, ToggleCaseSensitiveCommand, FindNext, FindPrevious, DeleteToLineStartTerminalAction } from 'vs/workbench/contrib/terminal/electron-browser/terminalActions'; +import { ClearSelectionTerminalAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, SplitInActiveWorkspaceTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction, ScrollToPreviousCommandAction, ScrollToNextCommandAction, SelectToPreviousCommandAction, SelectToNextCommandAction, SelectToPreviousLineAction, SelectToNextLineAction, ToggleEscapeSequenceLoggingAction, SendSequenceTerminalCommand, ToggleRegexCommand, ToggleWholeWordCommand, ToggleCaseSensitiveCommand, FindNext, FindPrevious, DeleteToLineStartTerminalAction, TERMINAL_PICKER_PREFIX, KillTerminalAction, CopyTerminalSelectionAction, SelectAllTerminalAction, ToggleTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { TerminalService } from 'vs/workbench/contrib/terminal/electron-browser/terminalService'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts index 7d301112c40..036053299f8 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts @@ -17,7 +17,7 @@ import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/contrib/termin import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget'; import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; -import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitTerminalAction } from 'vs/workbench/contrib/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { Panel } from 'vs/workbench/browser/panel'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { URI } from 'vs/base/common/uri'; From 3760c273fa12e6b89274049bb546fd013ae21ec5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:34:36 -0800 Subject: [PATCH 016/172] Move terminalPanel, electron-browser->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- .../terminalPanel.ts | 15 ++++++--------- .../workbench/contrib/terminal/common/terminal.ts | 1 + .../electron-browser/terminal.contribution.ts | 2 +- .../terminal/electron-browser/terminalService.ts | 2 +- src/vs/workbench/workbench.main.ts | 2 +- 6 files changed, 11 insertions(+), 13 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/terminalPanel.ts (96%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 19a576445ba..41f71cf9d5c 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -281,6 +281,7 @@ "./vs/workbench/contrib/terminal/browser/terminalActions.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", + "./vs/workbench/contrib/terminal/browser/terminalPanel.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", "./vs/workbench/contrib/terminal/browser/terminalTab.ts", "./vs/workbench/contrib/terminal/browser/terminalWidgetManager.ts", @@ -292,7 +293,6 @@ "./vs/workbench/contrib/terminal/common/terminalService.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalCommandTracker.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts similarity index 96% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts rename to src/vs/workbench/contrib/terminal/browser/terminalPanel.ts index 036053299f8..60286fd0e37 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts @@ -24,7 +24,6 @@ import { URI } from 'vs/base/common/uri'; import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { DataTransfers } from 'vs/base/browser/dnd'; import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; -import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; import { IStorageService } from 'vs/platform/storage/common/storage'; const FIND_FOCUS_CLASS = 'find-focused'; @@ -82,14 +81,12 @@ export class TerminalPanel extends Panel { if (e.affectsConfiguration('terminal.integrated.fontFamily') || e.affectsConfiguration('editor.fontFamily')) { const configHelper = this._terminalService.configHelper; - if (configHelper instanceof TerminalConfigHelper) { - if (!configHelper.configFontIsMonospace()) { - const choices: IPromptChoice[] = [{ - label: nls.localize('terminal.useMonospace', "Use 'monospace'"), - run: () => this._configurationService.updateValue('terminal.integrated.fontFamily', 'monospace'), - }]; - this._notificationService.prompt(Severity.Warning, nls.localize('terminal.monospaceOnly', "The terminal only supports monospace fonts."), choices); - } + if (!configHelper.configFontIsMonospace()) { + const choices: IPromptChoice[] = [{ + label: nls.localize('terminal.useMonospace', "Use 'monospace'"), + run: () => this._configurationService.updateValue('terminal.integrated.fontFamily', 'monospace'), + }]; + this._notificationService.prompt(Severity.Warning, nls.localize('terminal.monospaceOnly', "The terminal only supports monospace fonts."), choices); } } })); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 5673030976d..57217bb480c 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -107,6 +107,7 @@ export interface ITerminalConfiguration { export interface ITerminalConfigHelper { config: ITerminalConfiguration; + configFontIsMonospace(): boolean; getFont(): ITerminalFont; /** * Merges the default shell path and args into the provided launch configuration diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index 562568064b1..e703212b0b4 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -28,7 +28,7 @@ import { getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/qu import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { TerminalPanel } from 'vs/workbench/contrib/terminal/electron-browser/terminalPanel'; +import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 1914cf4af95..aa6c650d924 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -18,7 +18,7 @@ import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-bro import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; -import { TerminalPanel } from 'vs/workbench/contrib/terminal/electron-browser/terminalPanel'; +import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 7a1ce54df5f..84ed6ce8f02 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -154,7 +154,7 @@ import 'vs/workbench/contrib/output/browser/outputPanel'; // Terminal import 'vs/workbench/contrib/terminal/electron-browser/terminal.contribution'; import 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; -import 'vs/workbench/contrib/terminal/electron-browser/terminalPanel'; +import 'vs/workbench/contrib/terminal/browser/terminalPanel'; // Relauncher import 'vs/workbench/contrib/relauncher/electron-browser/relauncher.contribution'; From 2675ffeaafa5b91dd2102795543cde8e8f4d6075 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:39:47 -0800 Subject: [PATCH 017/172] Move parts of terminalService up to common/browser --- .../terminal/browser/terminalService.ts | 44 ++++++++++++- .../terminal/common/terminalService.ts | 33 ++++++++-- .../electron-browser/terminalService.ts | 65 ++----------------- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 060ce2863aa..7bf4664b9e6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -3,13 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITerminalService } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as CommonTerminalService } from 'vs/workbench/contrib/terminal/common/terminalService'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IStorageService } from 'vs/platform/storage/common/storage'; +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'; export abstract class TerminalService extends CommonTerminalService implements ITerminalService { @@ -18,8 +21,43 @@ export abstract class TerminalService extends CommonTerminalService implements I @IPanelService panelService: IPanelService, @IPartService partService: IPartService, @ILifecycleService lifecycleService: ILifecycleService, - @IStorageService storageService: IStorageService + @IStorageService storageService: IStorageService, + @INotificationService notificationService: INotificationService, + @IDialogService dialogService: IDialogService ) { - super(contextKeyService, panelService, partService, lifecycleService, storageService); + super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService); + } + + public focusFindWidget(): Promise { + return this.showPanel(false).then(() => { + const panel = this._panelService.getActivePanel() as TerminalPanel; + panel.focusFindWidget(); + this._findWidgetVisible.set(true); + }); + } + + public hideFindWidget(): void { + const panel = this._panelService.getActivePanel() as TerminalPanel; + if (panel && panel.getId() === TERMINAL_PANEL_ID) { + panel.hideFindWidget(); + this._findWidgetVisible.reset(); + panel.focus(); + } + } + + public findNext(): void { + const panel = this._panelService.getActivePanel() as TerminalPanel; + if (panel && panel.getId() === TERMINAL_PANEL_ID) { + panel.showFindWidget(); + panel.getFindWidget().find(false); + } + } + + public findPrevious(): void { + const panel = this._panelService.getActivePanel() as TerminalPanel; + if (panel && panel.getId() === TERMINAL_PANEL_ID) { + panel.showFindWidget(); + panel.getFindWidget().find(true); + } } } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 792ffad09b7..1999fd8a6ec 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -12,6 +13,8 @@ import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfi import { IStorageService } from 'vs/platform/storage/common/storage'; import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export abstract class TerminalService implements ITerminalService { public _serviceBrand: any; @@ -60,7 +63,9 @@ export abstract class TerminalService implements ITerminalService { @IPanelService protected readonly _panelService: IPanelService, @IPartService private readonly _partService: IPartService, @ILifecycleService lifecycleService: ILifecycleService, - @IStorageService protected readonly _storageService: IStorageService + @IStorageService protected readonly _storageService: IStorageService, + @INotificationService protected readonly _notificationService: INotificationService, + @IDialogService private readonly _dialogService: IDialogService ) { this._activeTabIndex = 0; this._isShuttingDown = false; @@ -88,11 +93,8 @@ export abstract class TerminalService implements ITerminalService { this.onInstancesChanged(() => updateTerminalContextKeys()); } - protected abstract _showTerminalCloseConfirmation(): Promise; - protected abstract _showNotEnoughSpaceToast(): void; public abstract createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; - public abstract getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): Promise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; public abstract requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void; @@ -101,6 +103,11 @@ export abstract class TerminalService implements ITerminalService { return this.createTerminal({ name, isRendererOnly: true }); } + public getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance { + const activeInstance = this.getActiveInstance(); + return activeInstance ? activeInstance : this.createTerminal(undefined, wasNewTerminalAction); + } + private _onBeforeShutdown(): boolean | Promise { if (this.terminalInstances.length === 0) { // No terminal instances, don't veto @@ -373,4 +380,22 @@ export abstract class TerminalService implements ITerminalService { public setWorkspaceShellAllowed(isAllowed: boolean): void { this.configHelper.setWorkspaceShellAllowed(isAllowed); } + + protected _showTerminalCloseConfirmation(): Promise { + let message; + if (this.terminalInstances.length === 1) { + message = nls.localize('terminalService.terminalCloseConfirmationSingular', "There is an active terminal session, do you want to kill it?"); + } else { + message = nls.localize('terminalService.terminalCloseConfirmationPlural', "There are {0} active terminal sessions, do you want to kill them?", this.terminalInstances.length); + } + + return this._dialogService.confirm({ + message, + type: 'warning', + }).then(res => !res.confirmed); + } + + protected _showNotEnoughSpaceToast(): void { + this._notificationService.info(nls.localize('terminal.minWidth', "Not enough space to split terminal.")); + } } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index aa6c650d924..b2739f6b45a 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -12,13 +12,12 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; -import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -43,12 +42,12 @@ export class TerminalService extends BrowserTerminalService implements ITerminal @IConfigurationService private readonly _configurationService: IConfigurationService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IQuickInputService private readonly _quickInputService: IQuickInputService, - @INotificationService private readonly _notificationService: INotificationService, - @IDialogService private readonly _dialogService: IDialogService, + @INotificationService notificationService: INotificationService, + @IDialogService dialogService: IDialogService, @IExtensionService private readonly _extensionService: IExtensionService, @IWindowService private readonly _windowService: IWindowService, ) { - super(contextKeyService, panelService, partService, lifecycleService, storageService); + super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService); this._terminalTabs = []; this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper); @@ -112,39 +111,6 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - public focusFindWidget(): Promise { - return this.showPanel(false).then(() => { - const panel = this._panelService.getActivePanel() as TerminalPanel; - panel.focusFindWidget(); - this._findWidgetVisible.set(true); - }); - } - - public hideFindWidget(): void { - const panel = this._panelService.getActivePanel() as TerminalPanel; - if (panel && panel.getId() === TERMINAL_PANEL_ID) { - panel.hideFindWidget(); - this._findWidgetVisible.reset(); - panel.focus(); - } - } - - public findNext(): void { - const panel = this._panelService.getActivePanel() as TerminalPanel; - if (panel && panel.getId() === TERMINAL_PANEL_ID) { - panel.showFindWidget(); - panel.getFindWidget().find(false); - } - } - - public findPrevious(): void { - const panel = this._panelService.getActivePanel() as TerminalPanel; - if (panel && panel.getId() === TERMINAL_PANEL_ID) { - panel.showFindWidget(); - panel.getFindWidget().find(true); - } - } - private _suggestShellChange(wasNewTerminalAction?: boolean): void { // Only suggest on Windows since $SHELL works great for macOS/Linux if (!platform.isWindows) { @@ -277,29 +243,6 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - public getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance { - const activeInstance = this.getActiveInstance(); - return activeInstance ? activeInstance : this.createTerminal(undefined, wasNewTerminalAction); - } - - protected _showTerminalCloseConfirmation(): Promise { - let message; - if (this.terminalInstances.length === 1) { - message = nls.localize('terminalService.terminalCloseConfirmationSingular', "There is an active terminal session, do you want to kill it?"); - } else { - message = nls.localize('terminalService.terminalCloseConfirmationPlural', "There are {0} active terminal sessions, do you want to kill them?", this.terminalInstances.length); - } - - return this._dialogService.confirm({ - message, - type: 'warning', - }).then(res => !res.confirmed); - } - - protected _showNotEnoughSpaceToast(): void { - this._notificationService.info(nls.localize('terminal.minWidth', "Not enough space to split terminal.")); - } - public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { this._configHelper.panelContainer = panelContainer; this._terminalContainer = terminalContainer; From 1d1dbdc494a7e7821ea77c0bae5f57cd7a5c9f96 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 17:55:20 -0800 Subject: [PATCH 018/172] Move TerminalConfigHelper, electron-browser->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- .../terminalConfigHelper.ts | 8 +-- .../contrib/terminal/common/terminal.ts | 6 ++ .../terminal/common/terminalService.ts | 2 +- .../electron-browser/terminalInstance.ts | 2 +- .../electron-browser/terminalService.ts | 7 +- .../contrib/terminal/node/terminal.ts | 9 +-- .../terminalConfigHelper.test.ts | 69 ++++++++++--------- 8 files changed, 57 insertions(+), 48 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/terminalConfigHelper.ts (97%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 41f71cf9d5c..c0381030c46 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -279,6 +279,7 @@ "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", "./vs/workbench/contrib/terminal/browser/terminalActions.ts", + "./vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/browser/terminalPanel.ts", @@ -291,7 +292,6 @@ "./vs/workbench/contrib/terminal/common/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts similarity index 97% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts rename to src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index fd82c1a61fb..91a780466ad 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -10,9 +10,8 @@ import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/ed import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; -import { isFedora, isUbuntu } from 'vs/workbench/contrib/terminal/node/terminal'; import { Terminal as XTermTerminal } from 'vscode-xterm'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -31,6 +30,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { public config: ITerminalConfiguration; public constructor( + private readonly _linuxDistro: LinuxDistro, @IConfigurationService private readonly _configurationService: IConfigurationService, @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, @INotificationService private readonly _notificationService: INotificationService, @@ -118,10 +118,10 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { // Work around bad font on Fedora/Ubuntu if (!this.config.fontFamily) { - if (isFedora) { + if (this._linuxDistro === LinuxDistro.Fedora) { fontFamily = '\'DejaVu Sans Mono\', monospace'; } - if (isUbuntu) { + if (this._linuxDistro === LinuxDistro.Ubuntu) { fontFamily = '\'Ubuntu Mono\', monospace'; // Ubuntu mono is somehow smaller, so set fontSize a bit larger to get the same perceived size. diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 57217bb480c..a31e4c2c714 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -687,4 +687,10 @@ export interface ITerminalProcessExtHostRequest { activeWorkspaceRootUri: URI; cols: number; rows: number; +} + +export enum LinuxDistro { + Fedora, + Ubuntu, + Unknown } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 1999fd8a6ec..88b917fbf52 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -23,7 +23,7 @@ export abstract class TerminalService implements ITerminalService { protected _terminalFocusContextKey: IContextKey; protected _findWidgetVisible: IContextKey; protected _terminalContainer: HTMLElement; - protected _terminalTabs: ITerminalTab[]; + protected _terminalTabs: ITerminalTab[] = []; protected get _terminalInstances(): ITerminalInstance[] { return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), []); } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index 22f9378da7b..7341a54add6 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -30,7 +30,7 @@ import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/ter import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; -import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; +import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/electron-browser/terminalProcessManager'; import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/node/terminalCommandTracker'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index b2739f6b45a..483d22ccf89 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -14,10 +14,10 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; -import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; +import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getDefaultShell, linuxDistro } from 'vs/workbench/contrib/terminal/node/terminal'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -49,8 +49,7 @@ export class TerminalService extends BrowserTerminalService implements ITerminal ) { super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService); - this._terminalTabs = []; - this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper); + this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper, linuxDistro); ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => { // if the request to open files is coming in from the integrated terminal (identified though // the termProgram variable) and we are instructed to wait for editors close, wait for the diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 73b41c24e5d..96b165c2614 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -8,6 +8,7 @@ import * as platform from 'vs/base/common/platform'; import * as processes from 'vs/base/node/processes'; import { readFile, fileExists } from 'vs/base/node/pfs'; import { Event } from 'vs/base/common/event'; +import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; /** * An interface representing a raw terminal child process, this contains a subset of the @@ -78,6 +79,7 @@ function getTerminalDefaultShellWindows(): string { return _TERMINAL_DEFAULT_SHELL_WINDOWS; } +let detectedDistro = LinuxDistro.Unknown; if (platform.isLinux) { const file = '/etc/os-release'; fileExists(file).then(exists => { @@ -87,13 +89,12 @@ if (platform.isLinux) { readFile(file).then(b => { const contents = b.toString(); if (/NAME="?Fedora"?/.test(contents)) { - isFedora = true; + detectedDistro = LinuxDistro.Fedora; } else if (/NAME="?Ubuntu"?/.test(contents)) { - isUbuntu = true; + detectedDistro = LinuxDistro.Ubuntu; } }); }); } -export let isFedora = false; -export let isUbuntu = false; \ No newline at end of file +export const linuxDistro = detectedDistro; diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts index 4ee63fee360..e0110601c82 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/electron-browser/terminalConfigHelper'; +import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { isFedora, isUbuntu } from 'vs/workbench/contrib/terminal/node/terminal'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; suite('Workbench - TerminalConfigHelper', () => { let fixture: HTMLElement; @@ -21,22 +21,24 @@ suite('Workbench - TerminalConfigHelper', () => { configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: 'bar' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontFamily, 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily'); configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); // Recreate config helper as onDidChangeConfiguration isn't implemented in TestConfigurationService - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + configHelper = new TerminalConfigHelper(LinuxDistro.Fedora, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; - if (isFedora) { - assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); - } else if (isUbuntu) { - assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); - } else { - assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); - } + assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); }); test('TerminalConfigHelper - getFont fontSize', function () { @@ -52,7 +54,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 10 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); @@ -65,13 +67,14 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; - if (isUbuntu) { - assert.equal(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it'); - } else { - assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); - } + assert.equal(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); + configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); @@ -81,7 +84,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 1500 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it'); @@ -94,13 +97,13 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: null } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; - if (isUbuntu) { - assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set'); - } else { - assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); - } + assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); }); test('TerminalConfigHelper - getFont lineHeight', function () { @@ -116,7 +119,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 2 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight'); @@ -130,7 +133,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set'); }); @@ -143,7 +146,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -155,7 +158,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'sans-serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -167,7 +170,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); @@ -183,7 +186,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -199,7 +202,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -215,7 +218,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); From b5dcee0a3185de2e019cc8127cbc5f91ab2b1b29 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 18:01:47 -0800 Subject: [PATCH 019/172] Move terminal CSS and images to browser Part of #69115 --- .../media/configure-inverse.svg | 0 .../{electron-browser => browser}/media/configure.svg | 0 .../{electron-browser => browser}/media/kill-inverse.svg | 0 .../terminal/{electron-browser => browser}/media/kill.svg | 0 .../{electron-browser => browser}/media/new-inverse.svg | 0 .../terminal/{electron-browser => browser}/media/new.svg | 0 .../{electron-browser => browser}/media/scrollbar.css | 0 .../media/split-horizontal-inverse.svg | 0 .../media/split-horizontal.svg | 0 .../{electron-browser => browser}/media/split-inverse.svg | 0 .../{electron-browser => browser}/media/split.svg | 0 .../{electron-browser => browser}/media/terminal.css | 0 .../{electron-browser => browser}/media/widgets.css | 0 .../{electron-browser => browser}/media/xterm.css | 0 .../terminal/electron-browser/terminal.contribution.ts | 8 ++++---- 15 files changed, 4 insertions(+), 4 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/configure-inverse.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/configure.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/kill-inverse.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/kill.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/new-inverse.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/new.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/scrollbar.css (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/split-horizontal-inverse.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/split-horizontal.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/split-inverse.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/split.svg (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/terminal.css (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/widgets.css (100%) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/media/xterm.css (100%) diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/configure-inverse.svg b/src/vs/workbench/contrib/terminal/browser/media/configure-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/configure-inverse.svg rename to src/vs/workbench/contrib/terminal/browser/media/configure-inverse.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/configure.svg b/src/vs/workbench/contrib/terminal/browser/media/configure.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/configure.svg rename to src/vs/workbench/contrib/terminal/browser/media/configure.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/kill-inverse.svg b/src/vs/workbench/contrib/terminal/browser/media/kill-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/kill-inverse.svg rename to src/vs/workbench/contrib/terminal/browser/media/kill-inverse.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/kill.svg b/src/vs/workbench/contrib/terminal/browser/media/kill.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/kill.svg rename to src/vs/workbench/contrib/terminal/browser/media/kill.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/new-inverse.svg b/src/vs/workbench/contrib/terminal/browser/media/new-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/new-inverse.svg rename to src/vs/workbench/contrib/terminal/browser/media/new-inverse.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/new.svg b/src/vs/workbench/contrib/terminal/browser/media/new.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/new.svg rename to src/vs/workbench/contrib/terminal/browser/media/new.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/scrollbar.css b/src/vs/workbench/contrib/terminal/browser/media/scrollbar.css similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/scrollbar.css rename to src/vs/workbench/contrib/terminal/browser/media/scrollbar.css diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/split-horizontal-inverse.svg b/src/vs/workbench/contrib/terminal/browser/media/split-horizontal-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/split-horizontal-inverse.svg rename to src/vs/workbench/contrib/terminal/browser/media/split-horizontal-inverse.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/split-horizontal.svg b/src/vs/workbench/contrib/terminal/browser/media/split-horizontal.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/split-horizontal.svg rename to src/vs/workbench/contrib/terminal/browser/media/split-horizontal.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/split-inverse.svg b/src/vs/workbench/contrib/terminal/browser/media/split-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/split-inverse.svg rename to src/vs/workbench/contrib/terminal/browser/media/split-inverse.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/split.svg b/src/vs/workbench/contrib/terminal/browser/media/split.svg similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/split.svg rename to src/vs/workbench/contrib/terminal/browser/media/split.svg diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/terminal.css rename to src/vs/workbench/contrib/terminal/browser/media/terminal.css diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/widgets.css b/src/vs/workbench/contrib/terminal/browser/media/widgets.css similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/widgets.css rename to src/vs/workbench/contrib/terminal/browser/media/widgets.css diff --git a/src/vs/workbench/contrib/terminal/electron-browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/media/xterm.css rename to src/vs/workbench/contrib/terminal/browser/media/xterm.css diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index e703212b0b4..e278b7ee47e 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/scrollbar'; -import 'vs/css!./media/terminal'; -import 'vs/css!./media/xterm'; -import 'vs/css!./media/widgets'; +import 'vs/css!../browser/media/scrollbar'; +import 'vs/css!../browser/media/terminal'; +import 'vs/css!../browser/media/xterm'; +import 'vs/css!../browser/media/widgets'; import * as nls from 'vs/nls'; import * as panel from 'vs/workbench/browser/panel'; import * as platform from 'vs/base/common/platform'; From 00f5bdb0ba79ad1d7a93815afde7486640df708e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 18:04:05 -0800 Subject: [PATCH 020/172] Move terminalCommandTracker, node->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 4 ++-- .../terminal/{node => browser}/terminalCommandTracker.ts | 0 .../contrib/terminal/electron-browser/terminalInstance.ts | 2 +- .../{node => electron-browser}/terminalCommandTracker.test.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/vs/workbench/contrib/terminal/{node => browser}/terminalCommandTracker.ts (100%) rename src/vs/workbench/contrib/terminal/test/{node => electron-browser}/terminalCommandTracker.test.ts (99%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index c0381030c46..e3974e6fdcc 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -279,6 +279,7 @@ "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", "./vs/workbench/contrib/terminal/browser/terminalActions.ts", + "./vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts", "./vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", @@ -295,14 +296,13 @@ "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", - "./vs/workbench/contrib/terminal/node/terminalCommandTracker.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", "./vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalColorRegistry.test.ts", + "./vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts", - "./vs/workbench/contrib/terminal/test/node/terminalCommandTracker.test.ts", "./vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts", "./vs/workbench/contrib/themes/browser/themes.contribution.ts", "./vs/workbench/contrib/themes/test/electron-browser/themes.test.contribution.ts", diff --git a/src/vs/workbench/contrib/terminal/node/terminalCommandTracker.ts b/src/vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts similarity index 100% rename from src/vs/workbench/contrib/terminal/node/terminalCommandTracker.ts rename to src/vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index 7341a54add6..dced8d25d78 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -33,7 +33,7 @@ import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/termin import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/electron-browser/terminalProcessManager'; -import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/node/terminalCommandTracker'; +import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/browser/terminalCommandTracker'; import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ISearchOptions, Terminal as XTermTerminal } from 'vscode-xterm'; diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalCommandTracker.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts similarity index 99% rename from src/vs/workbench/contrib/terminal/test/node/terminalCommandTracker.test.ts rename to src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts index 324781f164c..ec94ff8a518 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalCommandTracker.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { Terminal, TerminalCore } from 'vscode-xterm'; -import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/node/terminalCommandTracker'; +import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/browser/terminalCommandTracker'; import { isWindows } from 'vs/base/common/platform'; interface TestTerminalCore extends TerminalCore { From 415c08825d9b3cdd7530ccf4e37c3b19af231888 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 18:20:50 -0800 Subject: [PATCH 021/172] Move a lot of terminalService to common/browser --- .../terminal/browser/terminalService.ts | 107 ++++++++++++++- .../terminal/common/terminalService.ts | 30 ++++- .../electron-browser/terminalService.ts | 124 ++---------------- 3 files changed, 140 insertions(+), 121 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 7bf4664b9e6..051667c8a67 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -3,16 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import * as nls from 'vs/nls'; +import * as platform from 'vs/base/common/platform'; +import { ITerminalService, TERMINAL_PANEL_ID, ITerminalInstance, IShellLaunchConfig, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as CommonTerminalService } from 'vs/workbench/contrib/terminal/common/terminalService'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IStorageService } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; 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 { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IFileService } from 'vs/platform/files/common/files'; export abstract class TerminalService extends CommonTerminalService implements ITerminalService { @@ -23,9 +30,99 @@ export abstract class TerminalService extends CommonTerminalService implements I @ILifecycleService lifecycleService: ILifecycleService, @IStorageService storageService: IStorageService, @INotificationService notificationService: INotificationService, - @IDialogService dialogService: IDialogService + @IDialogService dialogService: IDialogService, + @IInstantiationService protected readonly _instantiationService: IInstantiationService, + @IWindowService private _windowService: IWindowService, + @IExtensionService extensionService: IExtensionService, + @IFileService fileService: IFileService ) { - super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService); + super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService, extensionService, fileService); + } + + protected abstract _getDefaultShell(p: platform.Platform): string; + + public createTerminal(shell: IShellLaunchConfig = {}, wasNewTerminalAction?: boolean): ITerminalInstance { + const terminalTab = this._instantiationService.createInstance(TerminalTab, + this._terminalFocusContextKey, + this.configHelper, + this._terminalContainer, + shell); + this._terminalTabs.push(terminalTab); + const instance = terminalTab.terminalInstances[0]; + terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); + terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); + this._initInstanceListeners(instance); + if (this.terminalInstances.length === 1) { + // It's the first instance so it should be made active automatically + this.setActiveInstanceByIndex(0); + } + this._onInstancesChanged.fire(); + this._suggestShellChange(wasNewTerminalAction); + return instance; + } + + private _suggestShellChange(wasNewTerminalAction?: boolean): void { + // Only suggest on Windows since $SHELL works great for macOS/Linux + if (!platform.isWindows) { + return; + } + + if (this._windowService.getConfiguration().remoteAuthority) { + // Don't suggest if the opened workspace is remote + return; + } + + // Only suggest when the terminal instance is being created by an explicit user action to + // launch a terminal, as opposed to something like tasks, debug, panel restore, etc. + if (!wasNewTerminalAction) { + return; + } + + if (this._windowService.getConfiguration().remoteAuthority) { + // Don't suggest if the opened workspace is remote + return; + } + + // Don't suggest if the user has explicitly opted out + const neverSuggest = this._storageService.getBoolean(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, StorageScope.GLOBAL, false); + if (neverSuggest) { + return; + } + + // Never suggest if the setting is non-default already (ie. they set the setting manually) + if (this.configHelper.config.shell.windows !== this._getDefaultShell(platform.Platform.Windows)) { + this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true, StorageScope.GLOBAL); + return; + } + + this._notificationService.prompt( + Severity.Info, + nls.localize('terminal.integrated.chooseWindowsShellInfo', "You can change the default terminal shell by selecting the customize button."), + [{ + label: nls.localize('customize', "Customize"), + run: () => { + this.selectDefaultWindowsShell().then(shell => { + if (!shell) { + return Promise.resolve(null); + } + // Launch a new instance with the newly selected shell + const instance = this.createTerminal({ + executable: shell, + args: this.configHelper.config.shellArgs.windows + }); + if (instance) { + this.setActiveInstance(instance); + } + return Promise.resolve(null); + }); + } + }, + { + label: nls.localize('never again', "Don't Show Again"), + isSecondary: true, + run: () => this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true, StorageScope.GLOBAL) + }] + ); } public focusFindWidget(): Promise { diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 88b917fbf52..3d3a3baac49 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -15,6 +15,8 @@ import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IFileService } from 'vs/platform/files/common/files'; export abstract class TerminalService implements ITerminalService { public _serviceBrand: any; @@ -65,7 +67,9 @@ export abstract class TerminalService implements ITerminalService { @ILifecycleService lifecycleService: ILifecycleService, @IStorageService protected readonly _storageService: IStorageService, @INotificationService protected readonly _notificationService: INotificationService, - @IDialogService private readonly _dialogService: IDialogService + @IDialogService private readonly _dialogService: IDialogService, + @IExtensionService private readonly _extensionService: IExtensionService, + @IFileService private readonly _fileService: IFileService ) { this._activeTabIndex = 0; this._isShuttingDown = false; @@ -97,7 +101,6 @@ export abstract class TerminalService implements ITerminalService { public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): Promise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; - public abstract requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void; public createTerminalRenderer(name: string): ITerminalInstance { return this.createTerminal({ name, isRendererOnly: true }); @@ -108,6 +111,16 @@ export abstract class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined, wasNewTerminalAction); } + public requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void { + // Ensure extension host is ready before requesting a process + this._extensionService.whenInstalledExtensionsRegistered().then(() => { + // TODO: MainThreadTerminalService is not ready at this point, fix this + setTimeout(() => { + this._onInstanceRequestExtHostProcess.fire({ proxy, shellLaunchConfig, activeWorkspaceRootUri, cols, rows }); + }, 500); + }); + } + private _onBeforeShutdown(): boolean | Promise { if (this.terminalInstances.length === 0) { // No terminal instances, don't veto @@ -398,4 +411,17 @@ export abstract class TerminalService implements ITerminalService { 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); + } + const current = potentialPaths.shift(); + return this._fileService.existsFile(URI.file(current!)).then(exists => { + if (!exists) { + return this._validateShellPaths(label, potentialPaths); + } + return [label, current] as [string, string]; + }); + } } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 483d22ccf89..95f089ef3fd 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -12,22 +12,20 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; -import Severity from 'vs/base/common/severity'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService } from 'vs/platform/storage/common/storage'; import { getDefaultShell, linuxDistro } from 'vs/workbench/contrib/terminal/node/terminal'; -import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ipcRenderer as ipc } from 'electron'; import { IOpenFileRequest, IWindowService } from 'vs/platform/windows/common/windows'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstance'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { URI } from 'vs/base/common/uri'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { coalesce } from 'vs/base/common/arrays'; +import { IFileService } from 'vs/platform/files/common/files'; export class TerminalService extends BrowserTerminalService implements ITerminalService { private _configHelper: TerminalConfigHelper; @@ -40,14 +38,15 @@ export class TerminalService extends BrowserTerminalService implements ITerminal @IStorageService storageService: IStorageService, @ILifecycleService lifecycleService: ILifecycleService, @IConfigurationService private readonly _configurationService: IConfigurationService, - @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IInstantiationService instantiationService: IInstantiationService, @IQuickInputService private readonly _quickInputService: IQuickInputService, @INotificationService notificationService: INotificationService, @IDialogService dialogService: IDialogService, - @IExtensionService private readonly _extensionService: IExtensionService, - @IWindowService private readonly _windowService: IWindowService, + @IExtensionService extensionService: IExtensionService, + @IWindowService windowService: IWindowService, + @IFileService fileService: IFileService ) { - super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService); + super(contextKeyService, panelService, partService, lifecycleService, storageService, notificationService, dialogService, instantiationService, windowService, extensionService, fileService); this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper, linuxDistro); ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => { @@ -74,104 +73,14 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - public createTerminal(shell: IShellLaunchConfig = {}, wasNewTerminalAction?: boolean): ITerminalInstance { - const terminalTab = this._instantiationService.createInstance(TerminalTab, - this._terminalFocusContextKey, - this._configHelper, - this._terminalContainer, - shell); - this._terminalTabs.push(terminalTab); - const instance = terminalTab.terminalInstances[0]; - terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); - terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); - this._initInstanceListeners(instance); - if (this.terminalInstances.length === 1) { - // It's the first instance so it should be made active automatically - this.setActiveInstanceByIndex(0); - } - this._onInstancesChanged.fire(); - this._suggestShellChange(wasNewTerminalAction); - return instance; - } - public createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance { const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig); this._onInstanceCreated.fire(instance); return instance; } - public requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void { - // Ensure extension host is ready before requesting a process - this._extensionService.whenInstalledExtensionsRegistered().then(() => { - // TODO: MainThreadTerminalService is not ready at this point, fix this - setTimeout(() => { - this._onInstanceRequestExtHostProcess.fire({ proxy, shellLaunchConfig, activeWorkspaceRootUri, cols, rows }); - }, 500); - }); - } - - private _suggestShellChange(wasNewTerminalAction?: boolean): void { - // Only suggest on Windows since $SHELL works great for macOS/Linux - if (!platform.isWindows) { - return; - } - - if (this._windowService.getConfiguration().remoteAuthority) { - // Don't suggest if the opened workspace is remote - return; - } - - // Only suggest when the terminal instance is being created by an explicit user action to - // launch a terminal, as opposed to something like tasks, debug, panel restore, etc. - if (!wasNewTerminalAction) { - return; - } - - if (this._windowService.getConfiguration().remoteAuthority) { - // Don't suggest if the opened workspace is remote - return; - } - - // Don't suggest if the user has explicitly opted out - const neverSuggest = this._storageService.getBoolean(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, StorageScope.GLOBAL, false); - if (neverSuggest) { - return; - } - - // Never suggest if the setting is non-default already (ie. they set the setting manually) - if (this._configHelper.config.shell.windows !== getDefaultShell(platform.Platform.Windows)) { - this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true, StorageScope.GLOBAL); - return; - } - - this._notificationService.prompt( - Severity.Info, - nls.localize('terminal.integrated.chooseWindowsShellInfo', "You can change the default terminal shell by selecting the customize button."), - [{ - label: nls.localize('customize', "Customize"), - run: () => { - this.selectDefaultWindowsShell().then(shell => { - if (!shell) { - return Promise.resolve(null); - } - // Launch a new instance with the newly selected shell - const instance = this.createTerminal({ - executable: shell, - args: this._configHelper.config.shellArgs.windows - }); - if (instance) { - this.setActiveInstance(instance); - } - return Promise.resolve(null); - }); - } - }, - { - label: nls.localize('never again', "Don't Show Again"), - isSecondary: true, - run: () => this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true, StorageScope.GLOBAL) - }] - ); + protected _getDefaultShell(p: platform.Platform): string { + return getDefaultShell(p); } public selectDefaultWindowsShell(): Promise { @@ -229,19 +138,6 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - private _validateShellPaths(label: string, potentialPaths: string[]): Promise<[string, string] | null> { - if (potentialPaths.length === 0) { - return Promise.resolve(null); - } - const current = potentialPaths.shift(); - return pfs.fileExists(current!).then(exists => { - if (!exists) { - return this._validateShellPaths(label, potentialPaths); - } - return [label, current] as [string, string]; - }); - } - public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { this._configHelper.panelContainer = panelContainer; this._terminalContainer = terminalContainer; From d9af6b90a069fb18fc458e49046e0a57e812329d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:18:01 -0800 Subject: [PATCH 022/172] Remove execFile dep in terminal instance, unify 2 path prep functions --- .../terminal/browser/terminalFindWidget.css | 4 --- .../contrib/terminal/browser/terminalPanel.ts | 7 ++-- .../terminal/common/terminalEnvironment.ts | 29 +++++----------- .../electron-browser/terminalInstance.ts | 34 +++---------------- .../electron-browser/terminalService.ts | 4 +-- .../contrib/terminal/node/terminal.ts | 26 ++++++++++++++ .../test/node/terminalEnvironment.test.ts | 10 ------ 7 files changed, 46 insertions(+), 68 deletions(-) delete mode 100644 src/vs/workbench/contrib/terminal/browser/terminalFindWidget.css diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.css b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.css deleted file mode 100644 index a4a092d8349..00000000000 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.css +++ /dev/null @@ -1,4 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ diff --git a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts index 60286fd0e37..67310672847 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts @@ -6,7 +6,6 @@ import * as dom from 'vs/base/browser/dom'; import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; -import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { Action, IAction } from 'vs/base/common/actions'; import { IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -281,7 +280,7 @@ export class TerminalPanel extends Panel { event.stopPropagation(); } })); - this._register(dom.addDisposableListener(this._parentDomElement, dom.EventType.DROP, (e: DragEvent) => { + this._register(dom.addDisposableListener(this._parentDomElement, dom.EventType.DROP, async (e: DragEvent) => { if (e.target === this._parentDomElement || dom.isAncestor(e.target as HTMLElement, this._parentDomElement)) { if (!e.dataTransfer) { return; @@ -303,7 +302,9 @@ export class TerminalPanel extends Panel { const terminal = this._terminalService.getActiveInstance(); if (terminal) { - terminal.sendText(terminalEnvironment.preparePathForTerminal(path), false); + return terminal.preparePathForTerminalAsync(path).then(preparedPath => { + terminal.sendText(preparedPath, false); + }); } } })); diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index cf8e7fab850..5480374bba8 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -132,26 +132,15 @@ function _sanitizeCwd(cwd: string): string { return cwd; } -/** - * Adds quotes to a path if it contains whitespaces - */ -export function preparePathForTerminal(path: string): string { - if (platform.isWindows) { - if (/\s+/.test(path)) { - return `"${path}"`; - } - return path; +export function escapeNonWindowsPath(path: string): string { + let newPath = path; + if (newPath.indexOf('\\') !== 0) { + newPath = newPath.replace(/\\/g, '\\\\'); } - path = path.replace(/(%5C|\\)/g, '\\\\'); - const charsToEscape = [ - ' ', '\'', '"', '?', ':', ';', '!', '*', '(', ')', '{', '}', '[', ']' - ]; - for (let i = 0; i < path.length; i++) { - const indexOfChar = charsToEscape.indexOf(path.charAt(i)); - if (indexOfChar >= 0) { - path = `${path.substring(0, i)}\\${path.charAt(i)}${path.substring(i + 1)}`; - i++; // Skip char due to escape char being added - } + if (!newPath && (newPath.indexOf('"') !== -1)) { + newPath = '\'' + newPath + '\''; + } else if (newPath.indexOf(' ') !== -1) { + newPath = newPath.replace(/ /g, '\\ '); } - return path; + return newPath; } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index dced8d25d78..7fe8f6286f0 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { execFile } from 'child_process'; -import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as dom from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -38,6 +36,8 @@ import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsSh import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ISearchOptions, Terminal as XTermTerminal } from 'vscode-xterm'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; +import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; +import { getWslPath, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; // How long in milliseconds should an average frame take to render for a notification to appear // which suggests the fallback DOM-based renderer @@ -829,10 +829,8 @@ export class TerminalInstance implements ITerminalInstance { if (platform.isWindows) { // 17063 is the build number where wsl path was introduced. // Update Windows uriPath to be executed in WSL. - if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (TerminalInstance.getWindowsBuildNumber() >= 17063)) { - execFile('bash.exe', ['-c', 'echo $(wslpath ' + this._escapeNonWindowsPath(originalPath) + ')'], {}, (error, stdout, stderr) => { - c(this._escapeNonWindowsPath(stdout.trim())); - }); + if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (getWindowsBuildNumber() >= 17063)) { + c(getWslPath(originalPath)); return; } else if (hasSpace) { c('"' + originalPath + '"'); @@ -841,32 +839,10 @@ export class TerminalInstance implements ITerminalInstance { } return; } - c(this._escapeNonWindowsPath(originalPath)); + c(escapeNonWindowsPath(originalPath)); }); } - private _escapeNonWindowsPath(path: string): string { - let newPath = path; - if (newPath.indexOf('\\') !== 0) { - newPath = newPath.replace(/\\/g, '\\\\'); - } - if (!newPath && (newPath.indexOf('"') !== -1)) { - newPath = '\'' + newPath + '\''; - } else if (newPath.indexOf(' ') !== -1) { - newPath = newPath.replace(/ /g, '\\ '); - } - return newPath; - } - - public static getWindowsBuildNumber(): number { - const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); - let buildNumber: number = 0; - if (osVersion && osVersion.length === 4) { - buildNumber = parseInt(osVersion[3]); - } - return buildNumber; - } - public setVisible(visible: boolean): void { this._isVisible = visible; if (this._wrapperElement) { diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 95f089ef3fd..86451a2b64f 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -16,7 +16,7 @@ import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfi import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { getDefaultShell, linuxDistro } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getDefaultShell, linuxDistro, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ipcRenderer as ipc } from 'electron'; @@ -108,7 +108,7 @@ export class TerminalService extends BrowserTerminalService implements ITerminal let useWSLexe = false; - if (TerminalInstance.getWindowsBuildNumber() >= 16299) { + if (getWindowsBuildNumber() >= 16299) { useWSLexe = true; } diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 96b165c2614..a7b76673023 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -9,6 +9,8 @@ import * as processes from 'vs/base/node/processes'; import { readFile, fileExists } from 'vs/base/node/pfs'; import { Event } from 'vs/base/common/event'; import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; +import { execFile } from 'child_process'; +import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; /** * An interface representing a raw terminal child process, this contains a subset of the @@ -98,3 +100,27 @@ if (platform.isLinux) { } export const linuxDistro = detectedDistro; + +export function getWindowsBuildNumber(): number { + const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); + let buildNumber: number = 0; + if (osVersion && osVersion.length === 4) { + buildNumber = parseInt(osVersion[3]); + } + return buildNumber; +} + +/** + * Converts a path to a path on WSL using the wslpath utility. + * @param path The original path. + */ +export function getWslPath(path: string): Promise { + if (getWindowsBuildNumber() < 17063) { + throw new Error('wslpath does not exist on Windows build < 17063'); + } + return new Promise(c => { + execFile('bash.exe', ['-c', 'echo $(wslpath ' + escapeNonWindowsPath(path) + ')'], {}, (error, stdout, stderr) => { + c(escapeNonWindowsPath(stdout.trim())); + }); + }); +} diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts index 6153a741193..58a8af973ec 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts @@ -128,14 +128,4 @@ suite('Workbench - TerminalEnvironment', () => { assertPathsMatch(terminalEnvironment.getCwd({ executable: undefined, args: [], ignoreConfigurationCwd: true }, '/userHome/', Uri.file('/bar'), '/foo'), '/bar'); }); }); - - test('preparePathForTerminal', () => { - if (platform.isWindows) { - assert.equal(terminalEnvironment.preparePathForTerminal('C:\\foo'), 'C:\\foo'); - assert.equal(terminalEnvironment.preparePathForTerminal('C:\\foo bar'), '"C:\\foo bar"'); - return; - } - assert.equal(terminalEnvironment.preparePathForTerminal('/a/\\foo bar"\'? ;\'?? :'), '/a/\\\\foo\\ bar\\"\\\'\\?\\ \\;\\\'\\?\\?\\ \\ \\:'); - assert.equal(terminalEnvironment.preparePathForTerminal('/\\\'"?:;!*(){}[]'), '/\\\\\\\'\\"\\?\\:\\;\\!\\*\\(\\)\\{\\}\\[\\]'); - }); }); From 877f0905acceb2299720d640bd781f624688aa0c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:20:07 -0800 Subject: [PATCH 023/172] Move terminalProcessManager to node --- src/tsconfig.strictNullChecks.json | 2 +- .../contrib/terminal/electron-browser/terminalInstance.ts | 2 +- .../{electron-browser => node}/terminalProcessManager.ts | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => node}/terminalProcessManager.ts (100%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index e3974e6fdcc..4db865ea10a 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -294,10 +294,10 @@ "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", "./vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts", + "./vs/workbench/contrib/terminal/node/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalColorRegistry.test.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index 7fe8f6286f0..62242b6373e 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -30,7 +30,7 @@ import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGR import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; -import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/electron-browser/terminalProcessManager'; +import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/node/terminalProcessManager'; import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/browser/terminalCommandTracker'; import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalProcessManager.ts rename to src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts From 23fbca34b08707f2d050c3a0326acd0808415679 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:51:18 -0800 Subject: [PATCH 024/172] Break node dependency in TerminalInstance --- .../contrib/terminal/browser/terminal.ts | 18 +++++ .../terminal/browser/terminalActions.ts | 2 +- .../contrib/terminal/browser/terminalPanel.ts | 2 +- .../contrib/terminal/common/terminal.ts | 30 +++++---- .../terminal/common/terminalService.ts | 1 + .../electron-browser/terminal.contribution.ts | 3 + .../electron-browser/terminalInstance.ts | 66 ++----------------- .../terminalInstanceService.ts | 50 ++++++++++++++ .../electron-browser/terminalService.ts | 42 +++++++++++- .../terminal/node/windowsShellHelper.ts | 4 +- 10 files changed, 141 insertions(+), 77 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/browser/terminal.ts create mode 100644 src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts new file mode 100644 index 00000000000..6fec000ba2d --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Terminal as XTermTerminal } from 'vscode-xterm'; +import { ITerminalInstance, IWindowsShellHelper, ITerminalProcessManager, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const ITerminalInstanceService = createDecorator('terminalInstanceService'); + +export interface ITerminalInstanceService { + _serviceBrand: any; + + getXtermConstructor(): Promise; + createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper; + createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager; +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index ea11c54029c..663829a2683 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -696,7 +696,7 @@ export class RunActiveFileInTerminalAction extends Action { return Promise.resolve(undefined); } - return instance.preparePathForTerminalAsync(uri.fsPath).then(path => { + return this.terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title).then(path => { instance.sendText(path, true); return this.terminalService.showPanel(); }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts index 67310672847..b248acd1af3 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalPanel.ts @@ -302,7 +302,7 @@ export class TerminalPanel extends Panel { const terminal = this._terminalService.getActiveInstance(); if (terminal) { - return terminal.preparePathForTerminalAsync(path).then(preparedPath => { + return this._terminalService.preparePathForTerminalAsync(path, terminal.shellLaunchConfig.executable, terminal.title).then(preparedPath => { terminal.sendText(preparedPath, false); }); } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index a31e4c2c714..c10fdf3a012 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -13,8 +13,6 @@ import { FindReplaceState } from 'vs/editor/contrib/find/findState'; export const TERMINAL_PANEL_ID = 'workbench.panel.terminal'; -export const TERMINAL_SERVICE_ID = 'terminalService'; - /** A context key that is set when there is at least one opened integrated terminal. */ export const KEYBINDING_CONTEXT_TERMINAL_IS_OPEN = new RawContextKey('terminalIsOpen', false); /** A context key that is set when the integrated terminal has focus. */ @@ -47,7 +45,7 @@ export const NEVER_MEASURE_RENDER_TIME_STORAGE_KEY = 'terminal.integrated.neverM // trying to create the corressponding object on the ext host. export const EXT_HOST_CREATION_DELAY = 100; -export const ITerminalService = createDecorator(TERMINAL_SERVICE_ID); +export const ITerminalService = createDecorator('terminalService'); export const TerminalCursorStyle = { BLOCK: 'block', @@ -255,6 +253,17 @@ export interface ITerminalService { selectDefaultWindowsShell(): Promise; setWorkspaceShellAllowed(isAllowed: boolean): void; + /** + * Takes a path and returns the properly escaped path to send to the terminal. + * On Windows, this included trying to prepare the path for WSL if needed. + * + * @param executable The executable off the shellLaunchConfig + * @param title The terminal's title + * @param path The path to be escaped and formatted. + * @returns An escaped version of the path to be execuded in the terminal. + */ + preparePathForTerminalAsync(path: string, executable: string | undefined, title: string): Promise; + requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number): void; } @@ -525,15 +534,6 @@ export interface ITerminalInstance { */ sendText(text: string, addNewLine: boolean): void; - /** - * Takes a path and returns the properly escaped path to send to the terminal. - * On Windows, this included trying to prepare the path for WSL if needed. - * - * @param path The path to be escaped and formatted. - * @returns An escaped version of the path to be execuded in the terminal. - */ - preparePathForTerminalAsync(path: string): Promise; - /** * Write text directly to the terminal, skipping the process if it exists. * @param text The text to write. @@ -693,4 +693,8 @@ export enum LinuxDistro { Fedora, Ubuntu, Unknown -} \ No newline at end of file +} + +export interface IWindowsShellHelper extends IDisposable { + getShellName(): Promise; +} diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 3d3a3baac49..859f4208b95 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -101,6 +101,7 @@ export abstract class TerminalService implements ITerminalService { public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): Promise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; + public abstract preparePathForTerminalAsync(path: string, executable: string, title: string): Promise; public createTerminalRenderer(name: string): ITerminalInstance { return this.createTerminal({ name, isRendererOnly: true }); diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index e278b7ee47e..a3e9ce8ad5f 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -33,6 +33,8 @@ import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/ter import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu'; import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstance'; +import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService'; +import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); @@ -291,6 +293,7 @@ configurationRegistry.registerConfiguration({ }); registerSingleton(ITerminalService, TerminalService, true); +registerSingleton(ITerminalInstanceService, TerminalInstanceService, true); (Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( TerminalPanel, diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts index 62242b6373e..08845402186 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts @@ -25,19 +25,16 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager'; -import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID, IWindowsShellHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler'; -import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/node/terminalProcessManager'; import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/browser/terminalCommandTracker'; -import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ISearchOptions, Terminal as XTermTerminal } from 'vscode-xterm'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; -import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -import { getWslPath, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; // How long in milliseconds should an average frame take to render for a notification to appear // which suggests the fallback DOM-based renderer @@ -151,8 +148,6 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ 'workbench.action.toggleMaximizedPanel' ]; -let Terminal: typeof XTermTerminal; - export class TerminalInstance implements ITerminalInstance { private static readonly EOL_REGEX = /\r?\n/g; @@ -175,7 +170,7 @@ export class TerminalInstance implements ITerminalInstance { private _cols: number; private _rows: number; private _dimensionsOverride: ITerminalDimensions; - private _windowsShellHelper: WindowsShellHelper | undefined; + private _windowsShellHelper: IWindowsShellHelper | undefined; private _xtermReadyPromise: Promise; private _titleReadyPromise: Promise; private _titleReadyComplete: (title: string) => any; @@ -240,6 +235,7 @@ export class TerminalInstance implements ITerminalInstance { private readonly _configHelper: TerminalConfigHelper, private _container: HTMLElement, private _shellLaunchConfig: IShellLaunchConfig, + @ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IKeybindingService private readonly _keybindingService: IKeybindingService, @INotificationService private readonly _notificationService: INotificationService, @@ -398,17 +394,7 @@ export class TerminalInstance implements ITerminalInstance { * Create xterm.js instance and attach data listeners. */ protected async _createXterm(): Promise { - if (!Terminal) { - Terminal = (await import('vscode-xterm')).Terminal; - // Enable xterm.js addons - Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/search/search')); - Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/webLinks/webLinks')); - Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/winptyCompat/winptyCompat')); - // Localize strings - Terminal.strings.blankLine = nls.localize('terminal.integrated.a11yBlankLine', 'Blank line'); - Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input'); - Terminal.strings.tooMuchOutput = nls.localize('terminal.integrated.a11yTooMuchOutput', 'Too much output to announce, navigate to rows manually to read'); - } + const Terminal = await this._terminalInstanceService.getXtermConstructor(); const font = this._configHelper.getFont(undefined, true); const config = this._configHelper.config; this._xterm = new Terminal({ @@ -805,44 +791,6 @@ export class TerminalInstance implements ITerminalInstance { } } - public preparePathForTerminalAsync(originalPath: string): Promise { - return new Promise(c => { - const exe = this.shellLaunchConfig.executable; - if (!exe) { - c(originalPath); - return; - } - - const hasSpace = originalPath.indexOf(' ') !== -1; - - const pathBasename = path.basename(exe, '.exe'); - const isPowerShell = pathBasename === 'pwsh' || - this.title === 'pwsh' || - pathBasename === 'powershell' || - this.title === 'powershell'; - - if (isPowerShell && (hasSpace || originalPath.indexOf('\'') !== -1)) { - c(`& '${originalPath.replace(/'/g, '\'\'')}'`); - return; - } - - if (platform.isWindows) { - // 17063 is the build number where wsl path was introduced. - // Update Windows uriPath to be executed in WSL. - if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (getWindowsBuildNumber() >= 17063)) { - c(getWslPath(originalPath)); - return; - } else if (hasSpace) { - c('"' + originalPath + '"'); - } else { - c(originalPath); - } - return; - } - c(escapeNonWindowsPath(originalPath)); - }); - } - public setVisible(visible: boolean): void { this._isVisible = visible; if (this._wrapperElement) { @@ -907,7 +855,7 @@ export class TerminalInstance implements ITerminalInstance { } protected _createProcess(): void { - this._processManager = this._instantiationService.createInstance(TerminalProcessManager, this._id, this._configHelper); + this._processManager = this._terminalInstanceService.createTerminalProcessManager(this._id, this._configHelper); this._processManager.onProcessReady(() => this._onProcessIdReady.fire(this)); this._processManager.onProcessExit(exitCode => this._onProcessExit(exitCode)); this._processManager.onProcessData(data => this._onData.fire(data)); @@ -924,7 +872,7 @@ export class TerminalInstance implements ITerminalInstance { this._processManager.ptyProcessReady.then(() => { this._xtermReadyPromise.then(() => { if (!this._isDisposed) { - this._windowsShellHelper = new WindowsShellHelper(this._processManager!.shellProcessId, this, this._xterm); + this._terminalInstanceService.createWindowsShellHelper(this._processManager!.shellProcessId, this, this._xterm); } }); }); diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts new file mode 100644 index 00000000000..727e5ab6201 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { Terminal as XTermTerminal } from 'vscode-xterm'; +import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; +import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/node/terminalProcessManager'; + +let Terminal: typeof XTermTerminal; + +/** + * A service used by TerminalInstance that allows it to break its dependency on electron-browser and + * node layers, while at the same time avoiding a cyclic dependency on ITerminalService. + */ +export class TerminalInstanceService implements ITerminalInstanceService { + public _serviceBrand: any; + + constructor( + @IInstantiationService private readonly _instantiationService: IInstantiationService, + ) { + } + + async getXtermConstructor(): Promise { + if (!Terminal) { + Terminal = (await import('vscode-xterm')).Terminal; + // Enable xterm.js addons + Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/search/search')); + Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/webLinks/webLinks')); + Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/winptyCompat/winptyCompat')); + // Localize strings + Terminal.strings.blankLine = nls.localize('terminal.integrated.a11yBlankLine', 'Blank line'); + Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input'); + Terminal.strings.tooMuchOutput = nls.localize('terminal.integrated.a11yTooMuchOutput', 'Too much output to announce, navigate to rows manually to read'); + } + return Terminal; + } + + createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper { + return new WindowsShellHelper(shellProcessId, instance, xterm); + } + + createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager { + return this._instantiationService.createInstance(TerminalProcessManager, id, configHelper); + } +} \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 86451a2b64f..44011e664d2 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -16,7 +16,7 @@ import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfi import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { getDefaultShell, linuxDistro, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getDefaultShell, linuxDistro, getWindowsBuildNumber, getWslPath } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ipcRenderer as ipc } from 'electron'; @@ -26,6 +26,8 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { coalesce } from 'vs/base/common/arrays'; import { IFileService } from 'vs/platform/files/common/files'; +import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; +import { basename } from 'vs/base/common/path'; export class TerminalService extends BrowserTerminalService implements ITerminalService { private _configHelper: TerminalConfigHelper; @@ -143,4 +145,42 @@ export class TerminalService extends BrowserTerminalService implements ITerminal this._terminalContainer = terminalContainer; this._terminalTabs.forEach(tab => tab.attachToElement(this._terminalContainer)); } + + public preparePathForTerminalAsync(originalPath: string, executable: string, title: string): Promise { + return new Promise(c => { + const exe = executable; + if (!exe) { + c(originalPath); + return; + } + + const hasSpace = originalPath.indexOf(' ') !== -1; + + const pathBasename = basename(exe, '.exe'); + const isPowerShell = pathBasename === 'pwsh' || + title === 'pwsh' || + pathBasename === 'powershell' || + title === 'powershell'; + + if (isPowerShell && (hasSpace || originalPath.indexOf('\'') !== -1)) { + c(`& '${originalPath.replace(/'/g, '\'\'')}'`); + return; + } + + if (platform.isWindows) { + // 17063 is the build number where wsl path was introduced. + // Update Windows uriPath to be executed in WSL. + if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (getWindowsBuildNumber() >= 17063)) { + c(getWslPath(originalPath)); + return; + } else if (hasSpace) { + c('"' + originalPath + '"'); + } else { + c(originalPath); + } + return; + } + c(escapeNonWindowsPath(originalPath)); + }); + } } diff --git a/src/vs/workbench/contrib/terminal/node/windowsShellHelper.ts b/src/vs/workbench/contrib/terminal/node/windowsShellHelper.ts index 80233f87d4d..d841d023695 100644 --- a/src/vs/workbench/contrib/terminal/node/windowsShellHelper.ts +++ b/src/vs/workbench/contrib/terminal/node/windowsShellHelper.ts @@ -5,7 +5,7 @@ import * as platform from 'vs/base/common/platform'; import { Emitter, Event } from 'vs/base/common/event'; -import { ITerminalInstance } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, IWindowsShellHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { Terminal as XTermTerminal } from 'vscode-xterm'; import WindowsProcessTreeType = require('windows-process-tree'); @@ -24,7 +24,7 @@ const SHELL_EXECUTABLES = [ let windowsProcessTree: typeof WindowsProcessTreeType; -export class WindowsShellHelper { +export class WindowsShellHelper implements IWindowsShellHelper { private _onCheckShell: Emitter | undefined>; private _isDisposed: boolean; private _currentRequest: Promise | null; From b5a06ebb62ba322549cf2c1f1c318a6d69ebeefa Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:52:20 -0800 Subject: [PATCH 025/172] Move terminalInstance, electron-browser->browser Part of #69115 --- src/tsconfig.strictNullChecks.json | 2 +- .../terminal/{electron-browser => browser}/terminalInstance.ts | 0 .../contrib/terminal/electron-browser/terminal.contribution.ts | 2 +- .../contrib/terminal/electron-browser/terminalService.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/vs/workbench/contrib/terminal/{electron-browser => browser}/terminalInstance.ts (100%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 4db865ea10a..b1be79b7e9f 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -282,6 +282,7 @@ "./vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts", "./vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts", "./vs/workbench/contrib/terminal/browser/terminalFindWidget.ts", + "./vs/workbench/contrib/terminal/browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/browser/terminalPanel.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", @@ -293,7 +294,6 @@ "./vs/workbench/contrib/terminal/common/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", - "./vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", "./vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts", diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts similarity index 100% rename from src/vs/workbench/contrib/terminal/electron-browser/terminalInstance.ts rename to src/vs/workbench/contrib/terminal/browser/terminalInstance.ts diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index a3e9ce8ad5f..d4cec6691ce 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -32,7 +32,7 @@ import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPan import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu'; -import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstance'; +import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 44011e664d2..2db2dcb3272 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -21,7 +21,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ipcRenderer as ipc } from 'electron'; import { IOpenFileRequest, IWindowService } from 'vs/platform/windows/common/windows'; -import { TerminalInstance } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstance'; +import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { coalesce } from 'vs/base/common/arrays'; From 03f23ddbc6fb37fcaba2877281c2593d05f24065 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:55:42 -0800 Subject: [PATCH 026/172] Remove duplicate getWindowsBuildNumber definitions --- .../tasks/electron-browser/terminalTaskSystem.ts | 13 ++----------- .../contrib/terminal/node/terminalProcess.ts | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts index bfaaf9c091a..025c9479cab 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts @@ -9,7 +9,6 @@ import * as Objects from 'vs/base/common/objects'; import * as Types from 'vs/base/common/types'; import * as Platform from 'vs/base/common/platform'; import * as Async from 'vs/base/common/async'; -import * as os from 'os'; import { IStringDictionary, values } from 'vs/base/common/collections'; import { LinkedMap, Touch } from 'vs/base/common/map'; import Severity from 'vs/base/common/severity'; @@ -42,6 +41,7 @@ import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts'; import { URI } from 'vs/base/common/uri'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { Schemas } from 'vs/base/common/network'; +import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; interface TerminalData { terminal: ITerminalInstance; @@ -745,7 +745,7 @@ export class TerminalTaskSystem implements ITaskSystem { if (!shellSpecified) { toAdd.push('-Command'); } - } else if ((basename === 'bash.exe') || (basename === 'zsh.exe') || ((basename === 'wsl.exe') && (this.getWindowsBuildNumber() < 17763))) { // See https://github.com/Microsoft/vscode/issues/67855 + } else if ((basename === 'bash.exe') || (basename === 'zsh.exe') || ((basename === 'wsl.exe') && (getWindowsBuildNumber() < 17763))) { // See https://github.com/Microsoft/vscode/issues/67855 windowsShellArgs = false; if (!shellSpecified) { toAdd.push('-c'); @@ -1213,15 +1213,6 @@ export class TerminalTaskSystem implements ITaskSystem { return result; } - private getWindowsBuildNumber(): number { - const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); - let buildNumber: number = 0; - if (osVersion && osVersion.length === 4) { - buildNumber = parseInt(osVersion[3]); - } - return buildNumber; - } - private registerLinkMatchers(terminal: ITerminalInstance, problemMatchers: ProblemMatcher[]): number[] { let result: number[] = []; /* diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index fbebae679ee..4aa6a76b158 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -9,7 +9,7 @@ import * as platform from 'vs/base/common/platform'; import * as pty from 'node-pty'; import * as fs from 'fs'; import { Event, Emitter } from 'vs/base/common/event'; -import { ITerminalChildProcess } from 'vs/workbench/contrib/terminal/node/terminal'; +import { ITerminalChildProcess, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; import { exec } from 'child_process'; @@ -51,7 +51,7 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { } this._initialCwd = cwd; - const useConpty = windowsEnableConpty && process.platform === 'win32' && this._getWindowsBuildNumber() >= 18309; + const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; const options: pty.IPtyForkOptions = { name: shellName, cwd, @@ -106,15 +106,6 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { this._onProcessTitleChanged.dispose(); } - private _getWindowsBuildNumber(): number { - const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); - let buildNumber: number = 0; - if (osVersion && osVersion.length === 4) { - buildNumber = parseInt(osVersion[3]); - } - return buildNumber; - } - private _setupTitlePolling() { // Send initial timeout async to give event listeners a chance to init setTimeout(() => { From 6d5ab922e68f689e05b39556ef9fbb1220f21db6 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 19:59:25 -0800 Subject: [PATCH 027/172] Move terminalProcessExtHostProxy, node->common --- src/tsconfig.strictNullChecks.json | 2 +- .../contrib/terminal/common/terminal.ts | 24 ++++++++++++++++++ .../terminalProcessExtHostProxy.ts | 3 +-- .../contrib/terminal/node/terminal.ts | 25 ------------------- .../contrib/terminal/node/terminalProcess.ts | 4 +-- .../terminal/node/terminalProcessManager.ts | 5 ++-- 6 files changed, 30 insertions(+), 33 deletions(-) rename src/vs/workbench/contrib/terminal/{node => common}/terminalProcessExtHostProxy.ts (96%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index b1be79b7e9f..13f40695a3c 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -293,10 +293,10 @@ "./vs/workbench/contrib/terminal/common/terminalCommands.ts", "./vs/workbench/contrib/terminal/common/terminalEnvironment.ts", "./vs/workbench/contrib/terminal/common/terminalMenu.ts", + "./vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", - "./vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts", "./vs/workbench/contrib/terminal/node/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalColorRegistry.test.ts", diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index c10fdf3a012..ec0303a0ea3 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -698,3 +698,27 @@ export enum LinuxDistro { export interface IWindowsShellHelper extends IDisposable { getShellName(): Promise; } + +/** + * An interface representing a raw terminal child process, this contains a subset of the + * child_process.ChildProcess node.js interface. + */ +export interface ITerminalChildProcess { + onProcessData: Event; + onProcessExit: Event; + onProcessIdReady: Event; + onProcessTitleChanged: Event; + + /** + * Shutdown the terminal process. + * + * @param immediate When true the process will be killed immediately, otherwise the process will + * be given some time to make sure no additional data comes through. + */ + shutdown(immediate: boolean): void; + input(data: string): void; + resize(cols: number, rows: number): void; + + getInitialCwd(): Promise; + getCwd(): Promise; +} \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts similarity index 96% rename from src/vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts rename to src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts index 5eb61629e48..84131aa9edd 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITerminalChildProcess } from 'vs/workbench/contrib/terminal/node/terminal'; import { Event, Emitter } from 'vs/base/common/event'; -import { ITerminalService, ITerminalProcessExtHostProxy, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalService, ITerminalProcessExtHostProxy, IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index a7b76673023..6200b9bf734 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -7,35 +7,10 @@ import * as os from 'os'; import * as platform from 'vs/base/common/platform'; import * as processes from 'vs/base/node/processes'; import { readFile, fileExists } from 'vs/base/node/pfs'; -import { Event } from 'vs/base/common/event'; import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import { execFile } from 'child_process'; import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -/** - * An interface representing a raw terminal child process, this contains a subset of the - * child_process.ChildProcess node.js interface. - */ -export interface ITerminalChildProcess { - onProcessData: Event; - onProcessExit: Event; - onProcessIdReady: Event; - onProcessTitleChanged: Event; - - /** - * Shutdown the terminal process. - * - * @param immediate When true the process will be killed immediately, otherwise the process will - * be given some time to make sure no additional data comes through. - */ - shutdown(immediate: boolean): void; - input(data: string): void; - resize(cols: number, rows: number): void; - - getInitialCwd(): Promise; - getCwd(): Promise; -} - export function getDefaultShell(p: platform.Platform): string { if (p === platform.Platform.Windows) { if (platform.isWindows) { diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 4aa6a76b158..3d40e7ed804 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -9,9 +9,9 @@ import * as platform from 'vs/base/common/platform'; import * as pty from 'node-pty'; import * as fs from 'fs'; import { Event, Emitter } from 'vs/base/common/event'; -import { ITerminalChildProcess, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { exec } from 'child_process'; export class TerminalProcess implements ITerminalChildProcess, IDisposable { diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts index 0a9923779e8..d46fcf801fc 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts @@ -6,12 +6,11 @@ import * as platform from 'vs/base/common/platform'; import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { ILogService } from 'vs/platform/log/common/log'; import { Emitter, Event } from 'vs/base/common/event'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { ITerminalChildProcess } from 'vs/workbench/contrib/terminal/node/terminal'; -import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/node/terminalProcessExtHostProxy'; +import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; From 437f7f67cb1f8d867a82445e3bdf97f545222675 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 20:10:07 -0800 Subject: [PATCH 028/172] Move TerminalProcessManager, node->browser --- src/tsconfig.strictNullChecks.json | 2 +- src/vs/base/common/processes.ts | 29 ++++++++++++++++ src/vs/base/node/processes.ts | 27 --------------- src/vs/base/test/common/processes.test.ts | 33 +++++++++++++++++++ .../test/node/processes/processes.test.ts | 25 -------------- .../api/node/extHostTerminalService.ts | 2 +- .../contrib/terminal/browser/terminal.ts | 4 ++- .../terminalProcessManager.ts | 9 ++--- .../terminalInstanceService.ts | 21 ++++++++---- 9 files changed, 86 insertions(+), 66 deletions(-) create mode 100644 src/vs/base/test/common/processes.test.ts rename src/vs/workbench/contrib/terminal/{node => browser}/terminalProcessManager.ts (96%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 13f40695a3c..8d70756d2f6 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -285,6 +285,7 @@ "./vs/workbench/contrib/terminal/browser/terminalInstance.ts", "./vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts", "./vs/workbench/contrib/terminal/browser/terminalPanel.ts", + "./vs/workbench/contrib/terminal/browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", "./vs/workbench/contrib/terminal/browser/terminalTab.ts", "./vs/workbench/contrib/terminal/browser/terminalWidgetManager.ts", @@ -297,7 +298,6 @@ "./vs/workbench/contrib/terminal/common/terminalService.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", - "./vs/workbench/contrib/terminal/node/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalColorRegistry.test.ts", "./vs/workbench/contrib/terminal/test/electron-browser/terminalCommandTracker.test.ts", diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts index 7eef74d894f..b42d8e25605 100644 --- a/src/vs/base/common/processes.ts +++ b/src/vs/base/common/processes.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IProcessEnvironment } from 'vs/base/common/platform'; + /** * Options to be passed to the external program or shell. */ @@ -84,3 +86,30 @@ export const enum TerminateResponseCode { AccessDenied = 2, ProcessNotFound = 3, } + +/** + * Sanitizes a VS Code process environment by removing all Electron/VS Code-related values. + */ +export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve: string[]): void { + const set = preserve.reduce((set, key) => { + set[key] = true; + return set; + }, {} as Record); + const keysToRemove = [ + /^ELECTRON_.+$/, + /^GOOGLE_API_KEY$/, + /^VSCODE_.+$/, + /^SNAP(|_.*)$/ + ]; + const envKeys = Object.keys(env); + envKeys + .filter(key => !set[key]) + .forEach(envKey => { + for (let i = 0; i < keysToRemove.length; i++) { + if (envKey.search(keysToRemove[i]) !== -1) { + delete env[envKey]; + break; + } + } + }); +} diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index dfaa9042499..9836e6ccfbb 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -72,33 +72,6 @@ export function getWindowsShell(): string { return process.env['comspec'] || 'cmd.exe'; } -/** - * Sanitizes a VS Code process environment by removing all Electron/VS Code-related values. - */ -export function sanitizeProcessEnvironment(env: Platform.IProcessEnvironment, ...preserve: string[]): void { - const set = preserve.reduce((set, key) => { - set[key] = true; - return set; - }, {} as Record); - const keysToRemove = [ - /^ELECTRON_.+$/, - /^GOOGLE_API_KEY$/, - /^VSCODE_.+$/, - /^SNAP(|_.*)$/ - ]; - const envKeys = Object.keys(env); - envKeys - .filter(key => !set[key]) - .forEach(envKey => { - for (let i = 0; i < keysToRemove.length; i++) { - if (envKey.search(keysToRemove[i]) !== -1) { - delete env[envKey]; - break; - } - } - }); -} - export abstract class AbstractProcess { private cmd: string; private args: string[]; diff --git a/src/vs/base/test/common/processes.test.ts b/src/vs/base/test/common/processes.test.ts new file mode 100644 index 00000000000..cd54b6fd724 --- /dev/null +++ b/src/vs/base/test/common/processes.test.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as processes from 'vs/base/common/processes'; + +suite('Processes', () => { + test('sanitizeProcessEnvironment', () => { + let env = { + FOO: 'bar', + ELECTRON_ENABLE_STACK_DUMPING: 'x', + ELECTRON_ENABLE_LOGGING: 'x', + ELECTRON_NO_ASAR: 'x', + ELECTRON_NO_ATTACH_CONSOLE: 'x', + ELECTRON_RUN_AS_NODE: 'x', + GOOGLE_API_KEY: 'x', + VSCODE_CLI: 'x', + VSCODE_DEV: 'x', + VSCODE_IPC_HOOK: 'x', + VSCODE_LOGS: 'x', + VSCODE_NLS_CONFIG: 'x', + VSCODE_PORTABLE: 'x', + VSCODE_PID: 'x', + VSCODE_NODE_CACHED_DATA_DIR: 'x', + VSCODE_NEW_VAR: 'x' + }; + processes.sanitizeProcessEnvironment(env); + assert.equal(env['FOO'], 'bar'); + assert.equal(Object.keys(env).length, 1); + }); +}); diff --git a/src/vs/base/test/node/processes/processes.test.ts b/src/vs/base/test/node/processes/processes.test.ts index 10199cf5bf3..76719506d6e 100644 --- a/src/vs/base/test/node/processes/processes.test.ts +++ b/src/vs/base/test/node/processes/processes.test.ts @@ -84,29 +84,4 @@ suite('Processes', () => { } }); }); - - - test('sanitizeProcessEnvironment', () => { - let env = { - FOO: 'bar', - ELECTRON_ENABLE_STACK_DUMPING: 'x', - ELECTRON_ENABLE_LOGGING: 'x', - ELECTRON_NO_ASAR: 'x', - ELECTRON_NO_ATTACH_CONSOLE: 'x', - ELECTRON_RUN_AS_NODE: 'x', - GOOGLE_API_KEY: 'x', - VSCODE_CLI: 'x', - VSCODE_DEV: 'x', - VSCODE_IPC_HOOK: 'x', - VSCODE_LOGS: 'x', - VSCODE_NLS_CONFIG: 'x', - VSCODE_PORTABLE: 'x', - VSCODE_PID: 'x', - VSCODE_NODE_CACHED_DATA_DIR: 'x', - VSCODE_NEW_VAR: 'x' - }; - processes.sanitizeProcessEnvironment(env); - assert.equal(env['FOO'], 'bar'); - assert.equal(Object.keys(env).length, 1); - }); }); diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 6f80fc77c38..070d8874c22 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -16,7 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { EXT_HOST_CREATION_DELAY } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { timeout } from 'vs/base/common/async'; -import { sanitizeProcessEnvironment } from 'vs/base/node/processes'; +import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; const RENDERER_NO_PROCESS_ID = -1; diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 6fec000ba2d..23114676b64 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Terminal as XTermTerminal } from 'vscode-xterm'; -import { ITerminalInstance, IWindowsShellHelper, ITerminalProcessManager, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, IWindowsShellHelper, ITerminalProcessManager, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IProcessEnvironment } from 'vs/base/common/platform'; export const ITerminalInstanceService = createDecorator('terminalInstanceService'); @@ -15,4 +16,5 @@ export interface ITerminalInstanceService { getXtermConstructor(): Promise; createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper; createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager; + createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess; } diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts similarity index 96% rename from src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts rename to src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index d46fcf801fc..18d6d58d78b 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -12,16 +12,16 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { Schemas } from 'vs/base/common/network'; import { REMOTE_HOST_SCHEME, getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; -import { sanitizeProcessEnvironment } from 'vs/base/node/processes'; +import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IProductService } from 'vs/platform/product/common/product'; +import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -63,7 +63,8 @@ export class TerminalProcessManager implements ITerminalProcessManager { @IWindowService private readonly _windowService: IWindowService, @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, - @IProductService private readonly _productService: IProductService + @IProductService private readonly _productService: IProductService, + @ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService ) { this.ptyProcessReady = new Promise(c => { this.onProcessReady(() => { @@ -148,7 +149,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { } this._logService.debug(`Terminal process launching`, shellLaunchConfig, initialCwd, cols, rows, env); - this._process = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, this._configHelper.config.windowsEnableConpty); + this._process = this._terminalInstanceService.createTerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, this._configHelper.config.windowsEnableConpty); } this.processState = ProcessState.LAUNCHING; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts index 727e5ab6201..d9d128e5f92 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -6,16 +6,19 @@ import * as nls from 'vs/nls'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { Terminal as XTermTerminal } from 'vscode-xterm'; -import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalProcessManager, IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/node/terminalProcessManager'; +import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager'; +import { IProcessEnvironment } from 'vs/base/common/platform'; +import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; let Terminal: typeof XTermTerminal; /** - * A service used by TerminalInstance that allows it to break its dependency on electron-browser and - * node layers, while at the same time avoiding a cyclic dependency on ITerminalService. + * A service used by TerminalInstance (and components owned by it) that allows it to break its + * dependency on electron-browser and node layers, while at the same time avoiding a cyclic + * dependency on ITerminalService. */ export class TerminalInstanceService implements ITerminalInstanceService { public _serviceBrand: any; @@ -25,7 +28,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { ) { } - async getXtermConstructor(): Promise { + public async getXtermConstructor(): Promise { if (!Terminal) { Terminal = (await import('vscode-xterm')).Terminal; // Enable xterm.js addons @@ -40,11 +43,15 @@ export class TerminalInstanceService implements ITerminalInstanceService { return Terminal; } - createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper { + public createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper { return new WindowsShellHelper(shellProcessId, instance, xterm); } - createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager { + public createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager { return this._instantiationService.createInstance(TerminalProcessManager, id, configHelper); } + + public createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess { + return new TerminalProcess(shellLaunchConfig, cwd, cols, rows, env, windowsEnableConpty); + } } \ No newline at end of file From ff5ae22403cdf705734d7822c89affca78564688 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 20:22:09 -0800 Subject: [PATCH 029/172] Remove more from electron-browser/terminalService --- .../contrib/terminal/browser/terminal.ts | 4 ++ .../terminal/browser/terminalConfigHelper.ts | 5 +- .../terminal/browser/terminalService.ts | 19 +++++- .../terminal/common/terminalService.ts | 45 ++++++++++++- .../electron-browser/terminalService.ts | 67 +++++-------------- .../contrib/terminal/node/terminal.ts | 17 ----- 6 files changed, 85 insertions(+), 72 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 23114676b64..ff7f6b95f5b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -18,3 +18,7 @@ export interface ITerminalInstanceService { createTerminalProcessManager(id: number, configHelper: ITerminalConfigHelper): ITerminalProcessManager; createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess; } + +export interface IBrowserTerminalConfigHelper extends ITerminalConfigHelper { + panelContainer: HTMLElement; +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index 91a780466ad..f4f0476caa0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -10,10 +10,11 @@ import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/ed import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalConfiguration, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; import { Terminal as XTermTerminal } from 'vscode-xterm'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal'; const MINIMUM_FONT_SIZE = 6; const MAXIMUM_FONT_SIZE = 25; @@ -22,7 +23,7 @@ const MAXIMUM_FONT_SIZE = 25; * Encapsulates terminal configuration logic, the primary purpose of this file is so that platform * specific test cases can be written. */ -export class TerminalConfigHelper implements ITerminalConfigHelper { +export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { public panelContainer: HTMLElement; private _charMeasureElement: HTMLElement; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 051667c8a67..28a01868122 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -5,9 +5,9 @@ import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; -import { ITerminalService, TERMINAL_PANEL_ID, ITerminalInstance, IShellLaunchConfig, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalService, TERMINAL_PANEL_ID, ITerminalInstance, IShellLaunchConfig, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as CommonTerminalService } from 'vs/workbench/contrib/terminal/common/terminalService'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -20,8 +20,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IWindowService } from 'vs/platform/windows/common/windows'; 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 } from 'vs/workbench/contrib/terminal/browser/terminal'; export abstract class TerminalService extends CommonTerminalService implements ITerminalService { + protected _configHelper: IBrowserTerminalConfigHelper; constructor( @IContextKeyService contextKeyService: IContextKeyService, @@ -41,6 +44,12 @@ export abstract class TerminalService extends CommonTerminalService implements I protected abstract _getDefaultShell(p: platform.Platform): string; + public createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance { + const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig); + this._onInstanceCreated.fire(instance); + return instance; + } + public createTerminal(shell: IShellLaunchConfig = {}, wasNewTerminalAction?: boolean): ITerminalInstance { const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalFocusContextKey, @@ -157,4 +166,10 @@ export abstract class TerminalService extends CommonTerminalService implements I panel.getFindWidget().find(true); } } + + public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { + this._configHelper.panelContainer = panelContainer; + this._terminalContainer = terminalContainer; + this._terminalTabs.forEach(tab => tab.attachToElement(this._terminalContainer)); + } } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 859f4208b95..b2d81641a84 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -17,6 +17,9 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; +import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; +import { isWindows } from 'vs/base/common/platform'; +import { basename } from 'vs/base/common/path'; export abstract class TerminalService implements ITerminalService { public _serviceBrand: any; @@ -97,11 +100,13 @@ export abstract class TerminalService implements ITerminalService { this.onInstancesChanged(() => updateTerminalContextKeys()); } + protected abstract _getWslPath(path: string): Promise; + protected abstract _getWindowsBuildNumber(): number; + public abstract createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): Promise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; - public abstract preparePathForTerminalAsync(path: string, executable: string, title: string): Promise; public createTerminalRenderer(name: string): ITerminalInstance { return this.createTerminal({ name, isRendererOnly: true }); @@ -425,4 +430,42 @@ export abstract class TerminalService implements ITerminalService { return [label, current] as [string, string]; }); } + + public preparePathForTerminalAsync(originalPath: string, executable: string, title: string): Promise { + return new Promise(c => { + const exe = executable; + if (!exe) { + c(originalPath); + return; + } + + const hasSpace = originalPath.indexOf(' ') !== -1; + + const pathBasename = basename(exe, '.exe'); + const isPowerShell = pathBasename === 'pwsh' || + title === 'pwsh' || + pathBasename === 'powershell' || + title === 'powershell'; + + if (isPowerShell && (hasSpace || originalPath.indexOf('\'') !== -1)) { + c(`& '${originalPath.replace(/'/g, '\'\'')}'`); + return; + } + + if (isWindows) { + // 17063 is the build number where wsl path was introduced. + // Update Windows uriPath to be executed in WSL. + if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (this._getWindowsBuildNumber() >= 17063)) { + c(this._getWslPath(originalPath)); + return; + } else if (hasSpace) { + c('"' + originalPath + '"'); + } else { + c(originalPath); + } + return; + } + c(escapeNonWindowsPath(originalPath)); + }); + } } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts index 2db2dcb3272..34dc08eec10 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalService.ts @@ -6,31 +6,29 @@ import * as nls from 'vs/nls'; import * as pfs from 'vs/base/node/pfs'; import * as platform from 'vs/base/common/platform'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalService, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalService as BrowserTerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { getDefaultShell, linuxDistro, getWindowsBuildNumber, getWslPath } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getDefaultShell, linuxDistro, getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ipcRenderer as ipc } from 'electron'; import { IOpenFileRequest, IWindowService } from 'vs/platform/windows/common/windows'; -import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { coalesce } from 'vs/base/common/arrays'; import { IFileService } from 'vs/platform/files/common/files'; import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -import { basename } from 'vs/base/common/path'; +import { execFile } from 'child_process'; export class TerminalService extends BrowserTerminalService implements ITerminalService { - private _configHelper: TerminalConfigHelper; public get configHelper(): ITerminalConfigHelper { return this._configHelper; } constructor( @@ -75,12 +73,6 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - public createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance { - const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig); - this._onInstanceCreated.fire(instance); - return instance; - } - protected _getDefaultShell(p: platform.Platform): string { return getDefaultShell(p); } @@ -140,47 +132,22 @@ export class TerminalService extends BrowserTerminalService implements ITerminal }); } - public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { - this._configHelper.panelContainer = panelContainer; - this._terminalContainer = terminalContainer; - this._terminalTabs.forEach(tab => tab.attachToElement(this._terminalContainer)); + protected _getWindowsBuildNumber(): number { + return getWindowsBuildNumber(); } - public preparePathForTerminalAsync(originalPath: string, executable: string, title: string): Promise { + /** + * Converts a path to a path on WSL using the wslpath utility. + * @param path The original path. + */ + protected _getWslPath(path: string): Promise { + if (getWindowsBuildNumber() < 17063) { + throw new Error('wslpath does not exist on Windows build < 17063'); + } return new Promise(c => { - const exe = executable; - if (!exe) { - c(originalPath); - return; - } - - const hasSpace = originalPath.indexOf(' ') !== -1; - - const pathBasename = basename(exe, '.exe'); - const isPowerShell = pathBasename === 'pwsh' || - title === 'pwsh' || - pathBasename === 'powershell' || - title === 'powershell'; - - if (isPowerShell && (hasSpace || originalPath.indexOf('\'') !== -1)) { - c(`& '${originalPath.replace(/'/g, '\'\'')}'`); - return; - } - - if (platform.isWindows) { - // 17063 is the build number where wsl path was introduced. - // Update Windows uriPath to be executed in WSL. - if (((exe.indexOf('wsl') !== -1) || ((exe.indexOf('bash.exe') !== -1) && (exe.indexOf('git') === -1))) && (getWindowsBuildNumber() >= 17063)) { - c(getWslPath(originalPath)); - return; - } else if (hasSpace) { - c('"' + originalPath + '"'); - } else { - c(originalPath); - } - return; - } - c(escapeNonWindowsPath(originalPath)); + execFile('bash.exe', ['-c', 'echo $(wslpath ' + escapeNonWindowsPath(path) + ')'], {}, (error, stdout, stderr) => { + c(escapeNonWindowsPath(stdout.trim())); + }); }); } } diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 6200b9bf734..493fad0b833 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -8,8 +8,6 @@ import * as platform from 'vs/base/common/platform'; import * as processes from 'vs/base/node/processes'; import { readFile, fileExists } from 'vs/base/node/pfs'; import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; -import { execFile } from 'child_process'; -import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; export function getDefaultShell(p: platform.Platform): string { if (p === platform.Platform.Windows) { @@ -84,18 +82,3 @@ export function getWindowsBuildNumber(): number { } return buildNumber; } - -/** - * Converts a path to a path on WSL using the wslpath utility. - * @param path The original path. - */ -export function getWslPath(path: string): Promise { - if (getWindowsBuildNumber() < 17063) { - throw new Error('wslpath does not exist on Windows build < 17063'); - } - return new Promise(c => { - execFile('bash.exe', ['-c', 'echo $(wslpath ' + escapeNonWindowsPath(path) + ')'], {}, (error, stdout, stderr) => { - c(escapeNonWindowsPath(stdout.trim())); - }); - }); -} From 3a10272f1e43a8c4548d7f31704595a3831b2e41 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 4 Mar 2019 20:39:47 -0800 Subject: [PATCH 030/172] Create browser/terminal.contribution.ts --- .../terminal/browser/terminal.contribution.ts | 519 ++++++++++++++++++ .../terminal/browser/terminalFindWidget.ts | 1 - .../electron-browser/terminal.contribution.ts | 511 +---------------- src/vs/workbench/workbench.main.ts | 1 + 4 files changed, 526 insertions(+), 506 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts new file mode 100644 index 00000000000..a420a5355b3 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -0,0 +1,519 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import * as platform from 'vs/base/common/platform'; +import 'vs/css!./media/scrollbar'; +import 'vs/css!./media/terminal'; +import 'vs/css!./media/widgets'; +import 'vs/css!./media/xterm'; +import * as nls from 'vs/nls'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as ActionBarExtensions, IActionBarRegistry, Scope } from 'vs/workbench/browser/actions'; +import * as panel from 'vs/workbench/browser/panel'; +import { getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen'; +import { Extensions as QuickOpenExtensions, IQuickOpenRegistry, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; +import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; +import { AllowWorkspaceShellTerminalCommand, ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, DisallowWorkspaceShellTerminalCommand, FindNext, FindPrevious, FocusActiveTerminalAction, FocusNextPaneTerminalAction, FocusNextTerminalAction, FocusPreviousPaneTerminalAction, FocusPreviousTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, KillTerminalAction, MoveToLineEndTerminalAction, MoveToLineStartTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, RenameTerminalAction, ResizePaneDownTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, RunActiveFileInTerminalAction, RunSelectedTextInTerminalAction, ScrollDownPageTerminalAction, ScrollDownTerminalAction, ScrollToBottomTerminalAction, ScrollToNextCommandAction, ScrollToPreviousCommandAction, ScrollToTopTerminalAction, ScrollUpPageTerminalAction, ScrollUpTerminalAction, SelectAllTerminalAction, SelectDefaultShellWindowsTerminalAction, SelectToNextCommandAction, SelectToNextLineAction, SelectToPreviousCommandAction, SelectToPreviousLineAction, SendSequenceTerminalCommand, SplitInActiveWorkspaceTerminalAction, SplitTerminalAction, TerminalPasteAction, TERMINAL_PICKER_PREFIX, ToggleCaseSensitiveCommand, ToggleEscapeSequenceLoggingAction, ToggleRegexCommand, ToggleTerminalAction, ToggleWholeWordCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions'; +import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; +import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; +import { KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle } from 'vs/workbench/contrib/terminal/common/terminal'; +import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; +import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; +import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu'; +import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; +import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; + +const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); + +const inTerminalsPicker = 'inTerminalPicker'; + +quickOpenRegistry.registerQuickOpenHandler( + new QuickOpenHandlerDescriptor( + TerminalPickerHandler, + TerminalPickerHandler.ID, + TERMINAL_PICKER_PREFIX, + inTerminalsPicker, + nls.localize('quickOpen.terminal', "Show All Opened Terminals") + ) +); + +const quickOpenNavigateNextInTerminalPickerId = 'workbench.action.quickOpenNavigateNextInTerminalPicker'; +CommandsRegistry.registerCommand( + { id: quickOpenNavigateNextInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigateNextInTerminalPickerId, true) }); + +const quickOpenNavigatePreviousInTerminalPickerId = 'workbench.action.quickOpenNavigatePreviousInTerminalPicker'; +CommandsRegistry.registerCommand( + { id: quickOpenNavigatePreviousInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigatePreviousInTerminalPickerId, false) }); + + +const configurationRegistry = Registry.as(Extensions.Configuration); +configurationRegistry.registerConfiguration({ + id: 'terminal', + order: 100, + title: nls.localize('terminalIntegratedConfigurationTitle', "Integrated Terminal"), + type: 'object', + properties: { + 'terminal.integrated.shellArgs.linux': { + markdownDescription: nls.localize('terminal.integrated.shellArgs.linux', "The command line arguments to use when on the Linux terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + type: 'array', + items: { + type: 'string' + }, + default: [] + }, + 'terminal.integrated.shellArgs.osx': { + markdownDescription: nls.localize('terminal.integrated.shellArgs.osx', "The command line arguments to use when on the macOS terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + type: 'array', + items: { + type: 'string' + }, + // Unlike on Linux, ~/.profile is not sourced when logging into a macOS session. This + // is the reason terminals on macOS typically run login shells by default which set up + // the environment. See http://unix.stackexchange.com/a/119675/115410 + default: ['-l'] + }, + 'terminal.integrated.shellArgs.windows': { + markdownDescription: nls.localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + 'anyOf': [ + { + type: 'array', + items: { + type: 'string', + markdownDescription: nls.localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).") + }, + }, + { + type: 'string', + markdownDescription: nls.localize('terminal.integrated.shellArgs.windows.string', "The command line arguments in [command-line format](https://msdn.microsoft.com/en-au/08dfcab2-eb6e-49a4-80eb-87d4076c98c6) to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).") + } + ], + default: [] + }, + 'terminal.integrated.macOptionIsMeta': { + description: nls.localize('terminal.integrated.macOptionIsMeta', "Controls whether to treat the option key as the meta key in the terminal on macOS."), + type: 'boolean', + default: false + }, + 'terminal.integrated.macOptionClickForcesSelection': { + description: nls.localize('terminal.integrated.macOptionClickForcesSelection', "Controls whether to force selection when using Option+click on macOS. This will force a regular (line) selection and disallow the use of column selection mode. This enables copying and pasting using the regular terminal selection, for example, when mouse mode is enabled in tmux."), + type: 'boolean', + default: false + }, + 'terminal.integrated.copyOnSelection': { + description: nls.localize('terminal.integrated.copyOnSelection', "Controls whether text selected in the terminal will be copied to the clipboard."), + type: 'boolean', + default: false + }, + 'terminal.integrated.drawBoldTextInBrightColors': { + description: nls.localize('terminal.integrated.drawBoldTextInBrightColors', "Controls whether bold text in the terminal will always use the \"bright\" ANSI color variant."), + type: 'boolean', + default: true + }, + 'terminal.integrated.fontFamily': { + markdownDescription: nls.localize('terminal.integrated.fontFamily', "Controls the font family of the terminal, this defaults to `#editor.fontFamily#`'s value."), + type: 'string' + }, + // TODO: Support font ligatures + // 'terminal.integrated.fontLigatures': { + // 'description': nls.localize('terminal.integrated.fontLigatures', "Controls whether font ligatures are enabled in the terminal."), + // 'type': 'boolean', + // 'default': false + // }, + 'terminal.integrated.fontSize': { + description: nls.localize('terminal.integrated.fontSize', "Controls the font size in pixels of the terminal."), + type: 'number', + default: EDITOR_FONT_DEFAULTS.fontSize + }, + 'terminal.integrated.letterSpacing': { + description: nls.localize('terminal.integrated.letterSpacing', "Controls the letter spacing of the terminal, this is an integer value which represents the amount of additional pixels to add between characters."), + type: 'number', + default: DEFAULT_LETTER_SPACING + }, + 'terminal.integrated.lineHeight': { + description: nls.localize('terminal.integrated.lineHeight', "Controls the line height of the terminal, this number is multiplied by the terminal font size to get the actual line-height in pixels."), + type: 'number', + default: DEFAULT_LINE_HEIGHT + }, + 'terminal.integrated.fontWeight': { + type: 'string', + enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], + description: nls.localize('terminal.integrated.fontWeight', "The font weight to use within the terminal for non-bold text."), + default: 'normal' + }, + 'terminal.integrated.fontWeightBold': { + type: 'string', + enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], + description: nls.localize('terminal.integrated.fontWeightBold', "The font weight to use within the terminal for bold text."), + default: 'bold' + }, + 'terminal.integrated.cursorBlinking': { + description: nls.localize('terminal.integrated.cursorBlinking', "Controls whether the terminal cursor blinks."), + type: 'boolean', + default: false + }, + 'terminal.integrated.cursorStyle': { + description: nls.localize('terminal.integrated.cursorStyle', "Controls the style of terminal cursor."), + enum: [TerminalCursorStyle.BLOCK, TerminalCursorStyle.LINE, TerminalCursorStyle.UNDERLINE], + default: TerminalCursorStyle.BLOCK + }, + 'terminal.integrated.scrollback': { + description: nls.localize('terminal.integrated.scrollback', "Controls the maximum amount of lines the terminal keeps in its buffer."), + type: 'number', + default: 1000 + }, + 'terminal.integrated.setLocaleVariables': { + markdownDescription: nls.localize('terminal.integrated.setLocaleVariables', "Controls whether locale variables are set at startup of the terminal."), + type: 'boolean', + default: true + }, + 'terminal.integrated.rendererType': { + type: 'string', + enum: ['auto', 'canvas', 'dom'], + enumDescriptions: [ + nls.localize('terminal.integrated.rendererType.auto', "Let VS Code guess which renderer to use."), + nls.localize('terminal.integrated.rendererType.canvas', "Use the standard GPU/canvas-based renderer"), + nls.localize('terminal.integrated.rendererType.dom', "Use the fallback DOM-based renderer.") + ], + default: 'auto', + description: nls.localize('terminal.integrated.rendererType', "Controls how the terminal is rendered.") + }, + 'terminal.integrated.rightClickBehavior': { + type: 'string', + enum: ['default', 'copyPaste', 'selectWord'], + enumDescriptions: [ + nls.localize('terminal.integrated.rightClickBehavior.default', "Show the context menu."), + nls.localize('terminal.integrated.rightClickBehavior.copyPaste', "Copy when there is a selection, otherwise paste."), + nls.localize('terminal.integrated.rightClickBehavior.selectWord', "Select the word under the cursor and show the context menu.") + ], + default: platform.isMacintosh ? 'selectWord' : platform.isWindows ? 'copyPaste' : 'default', + description: nls.localize('terminal.integrated.rightClickBehavior', "Controls how terminal reacts to right click.") + }, + 'terminal.integrated.cwd': { + description: nls.localize('terminal.integrated.cwd', "An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process. This may be particularly useful in workspace settings if the root directory is not a convenient cwd."), + type: 'string', + default: undefined + }, + 'terminal.integrated.confirmOnExit': { + description: nls.localize('terminal.integrated.confirmOnExit', "Controls whether to confirm on exit if there are active terminal sessions."), + type: 'boolean', + default: false + }, + 'terminal.integrated.enableBell': { + description: nls.localize('terminal.integrated.enableBell', "Controls whether the terminal bell is enabled."), + type: 'boolean', + default: false + }, + 'terminal.integrated.commandsToSkipShell': { + description: nls.localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')), + type: 'array', + items: { + type: 'string' + }, + default: [] + }, + 'terminal.integrated.env.osx': { + markdownDescription: nls.localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on macOS. Set to `null` to delete the environment variable."), + type: 'object', + additionalProperties: { + type: ['string', 'null'] + }, + default: {} + }, + 'terminal.integrated.env.linux': { + markdownDescription: nls.localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux. Set to `null` to delete the environment variable."), + type: 'object', + additionalProperties: { + type: ['string', 'null'] + }, + default: {} + }, + 'terminal.integrated.env.windows': { + markdownDescription: nls.localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows. Set to `null` to delete the environment variable."), + type: 'object', + additionalProperties: { + type: ['string', 'null'] + }, + default: {} + }, + 'terminal.integrated.showExitAlert': { + description: nls.localize('terminal.integrated.showExitAlert', "Controls whether to show the alert \"The terminal process terminated with exit code\" when exit code is non-zero."), + type: 'boolean', + default: true + }, + 'terminal.integrated.splitCwd': { + description: nls.localize('terminal.integrated.splitCwd', "Controls the working directory a split terminal starts with."), + type: 'string', + enum: ['workspaceRoot', 'initial', 'inherited'], + enumDescriptions: [ + nls.localize('terminal.integrated.splitCwd.workspaceRoot', "A new split terminal will use the workspace root as the working directory. In a multi-root workspace a choice for which root folder to use is offered."), + nls.localize('terminal.integrated.splitCwd.initial', "A new split terminal will use the working directory that the parent terminal started with."), + nls.localize('terminal.integrated.splitCwd.inherited', "On macOS and Linux, a new split terminal will use the working directory of the parent terminal. On Windows, this behaves the same as initial."), + ], + default: 'inherited' + }, + 'terminal.integrated.windowsEnableConpty': { + description: nls.localize('terminal.integrated.windowsEnableConpty', "Whether to use ConPTY for Windows terminal process communication (requires Windows 10 build number 18309+). Winpty will be used if this is false."), + type: 'boolean', + default: false + } + } +}); + +const registry = Registry.as(ActionExtensions.WorkbenchActions); +registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenTermAction, QuickOpenTermAction.ID, QuickOpenTermAction.LABEL), 'Terminal: Switch Active Terminal', nls.localize('terminal', "Terminal")); +const actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); +actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionTermContributor); + +(Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( + TerminalPanel, + TERMINAL_PANEL_ID, + nls.localize('terminal', "Terminal"), + 'terminal', + 40, + TERMINAL_COMMAND_ID.TOGGLE +)); + +// On mac cmd+` is reserved to cycle between windows, that's why the keybindings use WinCtrl +const category = nls.localize('terminalCategory', "Terminal"); +const actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.LABEL), 'Terminal: Kill the Active Terminal Instance', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_C, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C } +}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Copy Selection', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK, + mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK } +}), 'Terminal: Create New Integrated Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearSelectionTerminalAction, ClearSelectionTerminalAction.ID, ClearSelectionTerminalAction.LABEL, { + primary: KeyCode.Escape, + linux: { primary: KeyCode.Escape } +}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE)), 'Terminal: Escape selection', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewInActiveWorkspaceTerminalAction, CreateNewInActiveWorkspaceTerminalAction.ID, CreateNewInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (In Active Workspace)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_V, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V }, + // Don't apply to Mac since cmd+v works + mac: { primary: 0 } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL, { + // Don't use ctrl+a by default as that would override the common go to start + // of prompt shell binding + primary: 0, + // Technically this doesn't need to be here as it will fall back to this + // behavior anyway when handed to xterm.js, having this handled by VS Code + // makes it easier for users to see how it works though. + mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_A } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select All', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunSelectedTextInTerminalAction, RunSelectedTextInTerminalAction.ID, RunSelectedTextInTerminalAction.LABEL), 'Terminal: Run Selected Text In Active Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunActiveFileInTerminalAction, RunActiveFileInTerminalAction.ID, RunActiveFileInTerminalAction.LABEL), 'Terminal: Run Active File In Active Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK, + mac: { primary: KeyMod.WinCtrl | KeyCode.US_BACKTICK } +}), 'View: Toggle Integrated Terminal', nls.localize('viewCategory', "View")); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownTerminalAction, ScrollDownTerminalAction.ID, ScrollDownTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageDown, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Line)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownPageTerminalAction, ScrollDownPageTerminalAction.ID, ScrollDownPageTerminalAction.LABEL, { + primary: KeyMod.Shift | KeyCode.PageDown, + mac: { primary: KeyCode.PageDown } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Page)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToBottomTerminalAction, ScrollToBottomTerminalAction.ID, ScrollToBottomTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.End, + linux: { primary: KeyMod.Shift | KeyCode.End } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Bottom', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpTerminalAction, ScrollUpTerminalAction.ID, ScrollUpTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageUp, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Line)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpPageTerminalAction, ScrollUpPageTerminalAction.ID, ScrollUpPageTerminalAction.LABEL, { + primary: KeyMod.Shift | KeyCode.PageUp, + mac: { primary: KeyCode.PageUp } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Page)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToTopTerminalAction, ScrollToTopTerminalAction.ID, ScrollToTopTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.Home, + linux: { primary: KeyMod.Shift | KeyCode.Home } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Top', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearTerminalAction, ClearTerminalAction.ID, ClearTerminalAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_K } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KeybindingWeight.WorkbenchContrib + 1), 'Terminal: Clear', category); +if (platform.isWindows) { + actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectDefaultShellWindowsTerminalAction, SelectDefaultShellWindowsTerminalAction.ID, SelectDefaultShellWindowsTerminalAction.LABEL), 'Terminal: Select Default Shell', category); +} +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(AllowWorkspaceShellTerminalCommand, AllowWorkspaceShellTerminalCommand.ID, AllowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Allow Workspace Shell Configuration', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DisallowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand.ID, DisallowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Disallow Workspace Shell Configuration', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_F +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_F +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, { + primary: KeyCode.Escape, + secondary: [KeyMod.Shift | KeyCode.Escape] +}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE)), 'Terminal: Hide Find Widget', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteWordLeftTerminalAction, DeleteWordLeftTerminalAction.ID, DeleteWordLeftTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.Backspace, + mac: { primary: KeyMod.Alt | KeyCode.Backspace } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Left', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteWordRightTerminalAction, DeleteWordRightTerminalAction.ID, DeleteWordRightTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.Delete, + mac: { primary: KeyMod.Alt | KeyCode.Delete } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Right', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteToLineStartTerminalAction, DeleteToLineStartTerminalAction.ID, DeleteToLineStartTerminalAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete To Line Start', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(MoveToLineStartTerminalAction, MoveToLineStartTerminalAction.ID, MoveToLineStartTerminalAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.LeftArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line Start', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(MoveToLineEndTerminalAction, MoveToLineEndTerminalAction.ID, MoveToLineEndTerminalAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.RightArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line End', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH, + secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_5], + mac: { + primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH, + secondary: [KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_5] + } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitInActiveWorkspaceTerminalAction, SplitInActiveWorkspaceTerminalAction.ID, SplitInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Split Terminal (In Active Workspace)', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, { + primary: KeyMod.Alt | KeyCode.LeftArrow, + secondary: [KeyMod.Alt | KeyCode.UpArrow], + mac: { + primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.LeftArrow, + secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.UpArrow] + } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Previous Pane', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTerminalAction, FocusNextPaneTerminalAction.ID, FocusNextPaneTerminalAction.LABEL, { + primary: KeyMod.Alt | KeyCode.RightArrow, + secondary: [KeyMod.Alt | KeyCode.DownArrow], + mac: { + primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.RightArrow, + secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.DownArrow] + } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Next Pane', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, { + primary: 0, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow }, + mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Left', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, { + primary: 0, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow }, + mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Right', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, { + primary: 0, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, + mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.UpArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Up', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, { + primary: 0, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }, + mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Down', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToPreviousCommandAction, ScrollToPreviousCommandAction.ID, ScrollToPreviousCommandAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Previous Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToNextCommandAction, ScrollToNextCommandAction.ID, ScrollToNextCommandAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Next Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousCommandAction, SelectToPreviousCommandAction.ID, SelectToPreviousCommandAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Previous Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextCommandAction, SelectToNextCommandAction.ID, SelectToNextCommandAction.LABEL, { + primary: 0, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Next Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_R, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find by regex'); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID_TERMINAL_FOCUS, ToggleRegexCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_R, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find by regex', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_W, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find whole word'); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID_TERMINAL_FOCUS, ToggleWholeWordCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_W, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find whole word', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_C, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find match case'); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID_TERMINAL_FOCUS, ToggleCaseSensitiveCommand.LABEL, { + primary: KeyMod.Alt | KeyCode.KEY_C, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find match case', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID_TERMINAL_FOCUS, FindNext.LABEL, { + primary: KeyCode.F3, + mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find next', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID, FindNext.LABEL, { + primary: KeyCode.F3, + mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] } +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find next'); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID_TERMINAL_FOCUS, FindPrevious.LABEL, { + primary: KeyMod.Shift | KeyCode.F3, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] }, +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find previous', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID, FindPrevious.LABEL, { + primary: KeyMod.Shift | KeyCode.F3, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] }, +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find previous'); + + +const sendSequenceTerminalCommand = new SendSequenceTerminalCommand({ + id: SendSequenceTerminalCommand.ID, + precondition: null, + description: { + description: `Send Custom Sequence To Terminal`, + args: [{ + name: 'args', + schema: { + 'type': 'object', + 'required': ['text'], + 'properties': { + 'text': { + 'type': 'string' + } + }, + } + }] + } +}); +sendSequenceTerminalCommand.register(); + +setupTerminalCommands(); +setupTerminalMenu(); + +registerColors(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts index e5a54d0ba74..db30d122c39 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./terminalFindWidget'; import { SimpleFindWidget } from 'vs/editor/contrib/find/simpleFindWidget'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/terminal/common/terminal'; diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts index d4cec6691ce..a55b93caa40 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -3,66 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!../browser/media/scrollbar'; -import 'vs/css!../browser/media/terminal'; -import 'vs/css!../browser/media/xterm'; -import 'vs/css!../browser/media/widgets'; -import * as nls from 'vs/nls'; -import * as panel from 'vs/workbench/browser/panel'; import * as platform from 'vs/base/common/platform'; +import * as nls from 'vs/nls'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TerminalCursorStyle, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE, DEFAULT_LINE_HEIGHT, DEFAULT_LETTER_SPACING, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/terminal/common/terminal'; -import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; -import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { ClearSelectionTerminalAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, SplitInActiveWorkspaceTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction, ScrollToPreviousCommandAction, ScrollToNextCommandAction, SelectToPreviousCommandAction, SelectToNextCommandAction, SelectToPreviousLineAction, SelectToNextLineAction, ToggleEscapeSequenceLoggingAction, SendSequenceTerminalCommand, ToggleRegexCommand, ToggleWholeWordCommand, ToggleCaseSensitiveCommand, FindNext, FindPrevious, DeleteToLineStartTerminalAction, TERMINAL_PICKER_PREFIX, KillTerminalAction, CopyTerminalSelectionAction, SelectAllTerminalAction, ToggleTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { TerminalService } from 'vs/workbench/contrib/terminal/electron-browser/terminalService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; -import { getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen'; -import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; -import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel'; -import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; -import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands'; -import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu'; -import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; -import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService'; +import { Registry } from 'vs/platform/registry/common/platform'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; - -const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); - -const inTerminalsPicker = 'inTerminalPicker'; - -quickOpenRegistry.registerQuickOpenHandler( - new QuickOpenHandlerDescriptor( - TerminalPickerHandler, - TerminalPickerHandler.ID, - TERMINAL_PICKER_PREFIX, - inTerminalsPicker, - nls.localize('quickOpen.terminal', "Show All Opened Terminals") - ) -); - -const quickOpenNavigateNextInTerminalPickerId = 'workbench.action.quickOpenNavigateNextInTerminalPicker'; -CommandsRegistry.registerCommand( - { id: quickOpenNavigateNextInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigateNextInTerminalPickerId, true) }); - -const quickOpenNavigatePreviousInTerminalPickerId = 'workbench.action.quickOpenNavigatePreviousInTerminalPicker'; -CommandsRegistry.registerCommand( - { id: quickOpenNavigatePreviousInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigatePreviousInTerminalPickerId, false) }); - - -const registry = Registry.as(ActionExtensions.WorkbenchActions); -registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenTermAction, QuickOpenTermAction.ID, QuickOpenTermAction.LABEL), 'Terminal: Switch Active Terminal', nls.localize('terminal', "Terminal")); -const actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); -actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionTermContributor); +import { ITerminalService } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService'; +import { TerminalService } from 'vs/workbench/contrib/terminal/electron-browser/terminalService'; +import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; const configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration({ @@ -76,467 +26,18 @@ configurationRegistry.registerConfiguration({ type: 'string', default: getDefaultShell(platform.Platform.Linux) }, - 'terminal.integrated.shellArgs.linux': { - markdownDescription: nls.localize('terminal.integrated.shellArgs.linux', "The command line arguments to use when on the Linux terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), - type: 'array', - items: { - type: 'string' - }, - default: [] - }, 'terminal.integrated.shell.osx': { markdownDescription: nls.localize('terminal.integrated.shell.osx', "The path of the shell that the terminal uses on macOS. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), type: 'string', default: getDefaultShell(platform.Platform.Mac) }, - 'terminal.integrated.shellArgs.osx': { - markdownDescription: nls.localize('terminal.integrated.shellArgs.osx', "The command line arguments to use when on the macOS terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), - type: 'array', - items: { - type: 'string' - }, - // Unlike on Linux, ~/.profile is not sourced when logging into a macOS session. This - // is the reason terminals on macOS typically run login shells by default which set up - // the environment. See http://unix.stackexchange.com/a/119675/115410 - default: ['-l'] - }, 'terminal.integrated.shell.windows': { markdownDescription: nls.localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), type: 'string', default: getDefaultShell(platform.Platform.Windows) - }, - 'terminal.integrated.shellArgs.windows': { - markdownDescription: nls.localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), - 'anyOf': [ - { - type: 'array', - items: { - type: 'string', - markdownDescription: nls.localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).") - }, - }, - { - type: 'string', - markdownDescription: nls.localize('terminal.integrated.shellArgs.windows.string', "The command line arguments in [command-line format](https://msdn.microsoft.com/en-au/08dfcab2-eb6e-49a4-80eb-87d4076c98c6) to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).") - } - ], - default: [] - }, - 'terminal.integrated.macOptionIsMeta': { - description: nls.localize('terminal.integrated.macOptionIsMeta', "Controls whether to treat the option key as the meta key in the terminal on macOS."), - type: 'boolean', - default: false - }, - 'terminal.integrated.macOptionClickForcesSelection': { - description: nls.localize('terminal.integrated.macOptionClickForcesSelection', "Controls whether to force selection when using Option+click on macOS. This will force a regular (line) selection and disallow the use of column selection mode. This enables copying and pasting using the regular terminal selection, for example, when mouse mode is enabled in tmux."), - type: 'boolean', - default: false - }, - 'terminal.integrated.copyOnSelection': { - description: nls.localize('terminal.integrated.copyOnSelection', "Controls whether text selected in the terminal will be copied to the clipboard."), - type: 'boolean', - default: false - }, - 'terminal.integrated.drawBoldTextInBrightColors': { - description: nls.localize('terminal.integrated.drawBoldTextInBrightColors', "Controls whether bold text in the terminal will always use the \"bright\" ANSI color variant."), - type: 'boolean', - default: true - }, - 'terminal.integrated.fontFamily': { - markdownDescription: nls.localize('terminal.integrated.fontFamily', "Controls the font family of the terminal, this defaults to `#editor.fontFamily#`'s value."), - type: 'string' - }, - // TODO: Support font ligatures - // 'terminal.integrated.fontLigatures': { - // 'description': nls.localize('terminal.integrated.fontLigatures', "Controls whether font ligatures are enabled in the terminal."), - // 'type': 'boolean', - // 'default': false - // }, - 'terminal.integrated.fontSize': { - description: nls.localize('terminal.integrated.fontSize', "Controls the font size in pixels of the terminal."), - type: 'number', - default: EDITOR_FONT_DEFAULTS.fontSize - }, - 'terminal.integrated.letterSpacing': { - description: nls.localize('terminal.integrated.letterSpacing', "Controls the letter spacing of the terminal, this is an integer value which represents the amount of additional pixels to add between characters."), - type: 'number', - default: DEFAULT_LETTER_SPACING - }, - 'terminal.integrated.lineHeight': { - description: nls.localize('terminal.integrated.lineHeight', "Controls the line height of the terminal, this number is multiplied by the terminal font size to get the actual line-height in pixels."), - type: 'number', - default: DEFAULT_LINE_HEIGHT - }, - 'terminal.integrated.fontWeight': { - type: 'string', - enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], - description: nls.localize('terminal.integrated.fontWeight', "The font weight to use within the terminal for non-bold text."), - default: 'normal' - }, - 'terminal.integrated.fontWeightBold': { - type: 'string', - enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], - description: nls.localize('terminal.integrated.fontWeightBold', "The font weight to use within the terminal for bold text."), - default: 'bold' - }, - 'terminal.integrated.cursorBlinking': { - description: nls.localize('terminal.integrated.cursorBlinking', "Controls whether the terminal cursor blinks."), - type: 'boolean', - default: false - }, - 'terminal.integrated.cursorStyle': { - description: nls.localize('terminal.integrated.cursorStyle', "Controls the style of terminal cursor."), - enum: [TerminalCursorStyle.BLOCK, TerminalCursorStyle.LINE, TerminalCursorStyle.UNDERLINE], - default: TerminalCursorStyle.BLOCK - }, - 'terminal.integrated.scrollback': { - description: nls.localize('terminal.integrated.scrollback', "Controls the maximum amount of lines the terminal keeps in its buffer."), - type: 'number', - default: 1000 - }, - 'terminal.integrated.setLocaleVariables': { - markdownDescription: nls.localize('terminal.integrated.setLocaleVariables', "Controls whether locale variables are set at startup of the terminal."), - type: 'boolean', - default: true - }, - 'terminal.integrated.rendererType': { - type: 'string', - enum: ['auto', 'canvas', 'dom'], - enumDescriptions: [ - nls.localize('terminal.integrated.rendererType.auto', "Let VS Code guess which renderer to use."), - nls.localize('terminal.integrated.rendererType.canvas', "Use the standard GPU/canvas-based renderer"), - nls.localize('terminal.integrated.rendererType.dom', "Use the fallback DOM-based renderer.") - ], - default: 'auto', - description: nls.localize('terminal.integrated.rendererType', "Controls how the terminal is rendered.") - }, - 'terminal.integrated.rightClickBehavior': { - type: 'string', - enum: ['default', 'copyPaste', 'selectWord'], - enumDescriptions: [ - nls.localize('terminal.integrated.rightClickBehavior.default', "Show the context menu."), - nls.localize('terminal.integrated.rightClickBehavior.copyPaste', "Copy when there is a selection, otherwise paste."), - nls.localize('terminal.integrated.rightClickBehavior.selectWord', "Select the word under the cursor and show the context menu.") - ], - default: platform.isMacintosh ? 'selectWord' : platform.isWindows ? 'copyPaste' : 'default', - description: nls.localize('terminal.integrated.rightClickBehavior', "Controls how terminal reacts to right click.") - }, - 'terminal.integrated.cwd': { - description: nls.localize('terminal.integrated.cwd', "An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process. This may be particularly useful in workspace settings if the root directory is not a convenient cwd."), - type: 'string', - default: undefined - }, - 'terminal.integrated.confirmOnExit': { - description: nls.localize('terminal.integrated.confirmOnExit', "Controls whether to confirm on exit if there are active terminal sessions."), - type: 'boolean', - default: false - }, - 'terminal.integrated.enableBell': { - description: nls.localize('terminal.integrated.enableBell', "Controls whether the terminal bell is enabled."), - type: 'boolean', - default: false - }, - 'terminal.integrated.commandsToSkipShell': { - description: nls.localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')), - type: 'array', - items: { - type: 'string' - }, - default: [] - }, - 'terminal.integrated.env.osx': { - markdownDescription: nls.localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on macOS. Set to `null` to delete the environment variable."), - type: 'object', - additionalProperties: { - type: ['string', 'null'] - }, - default: {} - }, - 'terminal.integrated.env.linux': { - markdownDescription: nls.localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux. Set to `null` to delete the environment variable."), - type: 'object', - additionalProperties: { - type: ['string', 'null'] - }, - default: {} - }, - 'terminal.integrated.env.windows': { - markdownDescription: nls.localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows. Set to `null` to delete the environment variable."), - type: 'object', - additionalProperties: { - type: ['string', 'null'] - }, - default: {} - }, - 'terminal.integrated.showExitAlert': { - description: nls.localize('terminal.integrated.showExitAlert', "Controls whether to show the alert \"The terminal process terminated with exit code\" when exit code is non-zero."), - type: 'boolean', - default: true - }, - 'terminal.integrated.splitCwd': { - description: nls.localize('terminal.integrated.splitCwd', "Controls the working directory a split terminal starts with."), - type: 'string', - enum: ['workspaceRoot', 'initial', 'inherited'], - enumDescriptions: [ - nls.localize('terminal.integrated.splitCwd.workspaceRoot', "A new split terminal will use the workspace root as the working directory. In a multi-root workspace a choice for which root folder to use is offered."), - nls.localize('terminal.integrated.splitCwd.initial', "A new split terminal will use the working directory that the parent terminal started with."), - nls.localize('terminal.integrated.splitCwd.inherited', "On macOS and Linux, a new split terminal will use the working directory of the parent terminal. On Windows, this behaves the same as initial."), - ], - default: 'inherited' - }, - 'terminal.integrated.windowsEnableConpty': { - description: nls.localize('terminal.integrated.windowsEnableConpty', "Whether to use ConPTY for Windows terminal process communication (requires Windows 10 build number 18309+). Winpty will be used if this is false."), - type: 'boolean', - default: false } } }); registerSingleton(ITerminalService, TerminalService, true); registerSingleton(ITerminalInstanceService, TerminalInstanceService, true); - -(Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( - TerminalPanel, - TERMINAL_PANEL_ID, - nls.localize('terminal', "Terminal"), - 'terminal', - 40, - TERMINAL_COMMAND_ID.TOGGLE -)); - -// On mac cmd+` is reserved to cycle between windows, that's why the keybindings use WinCtrl -const category = nls.localize('terminalCategory', "Terminal"); -const actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.LABEL), 'Terminal: Kill the Active Terminal Instance', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.KEY_C, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C } -}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Copy Selection', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK, - mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK } -}), 'Terminal: Create New Integrated Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearSelectionTerminalAction, ClearSelectionTerminalAction.ID, ClearSelectionTerminalAction.LABEL, { - primary: KeyCode.Escape, - linux: { primary: KeyCode.Escape } -}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE)), 'Terminal: Escape selection', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewInActiveWorkspaceTerminalAction, CreateNewInActiveWorkspaceTerminalAction.ID, CreateNewInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (In Active Workspace)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.KEY_V, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V }, - // Don't apply to Mac since cmd+v works - mac: { primary: 0 } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL, { - // Don't use ctrl+a by default as that would override the common go to start - // of prompt shell binding - primary: 0, - // Technically this doesn't need to be here as it will fall back to this - // behavior anyway when handed to xterm.js, having this handled by VS Code - // makes it easier for users to see how it works though. - mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_A } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select All', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunSelectedTextInTerminalAction, RunSelectedTextInTerminalAction.ID, RunSelectedTextInTerminalAction.LABEL), 'Terminal: Run Selected Text In Active Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunActiveFileInTerminalAction, RunActiveFileInTerminalAction.ID, RunActiveFileInTerminalAction.LABEL), 'Terminal: Run Active File In Active Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK, - mac: { primary: KeyMod.WinCtrl | KeyCode.US_BACKTICK } -}), 'View: Toggle Integrated Terminal', nls.localize('viewCategory', "View")); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownTerminalAction, ScrollDownTerminalAction.ID, ScrollDownTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageDown, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Line)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownPageTerminalAction, ScrollDownPageTerminalAction.ID, ScrollDownPageTerminalAction.LABEL, { - primary: KeyMod.Shift | KeyCode.PageDown, - mac: { primary: KeyCode.PageDown } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Page)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToBottomTerminalAction, ScrollToBottomTerminalAction.ID, ScrollToBottomTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.End, - linux: { primary: KeyMod.Shift | KeyCode.End } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Bottom', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpTerminalAction, ScrollUpTerminalAction.ID, ScrollUpTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageUp, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Line)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpPageTerminalAction, ScrollUpPageTerminalAction.ID, ScrollUpPageTerminalAction.LABEL, { - primary: KeyMod.Shift | KeyCode.PageUp, - mac: { primary: KeyCode.PageUp } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Page)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToTopTerminalAction, ScrollToTopTerminalAction.ID, ScrollToTopTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.Home, - linux: { primary: KeyMod.Shift | KeyCode.Home } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Top', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearTerminalAction, ClearTerminalAction.ID, ClearTerminalAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_K } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KeybindingWeight.WorkbenchContrib + 1), 'Terminal: Clear', category); -if (platform.isWindows) { - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectDefaultShellWindowsTerminalAction, SelectDefaultShellWindowsTerminalAction.ID, SelectDefaultShellWindowsTerminalAction.LABEL), 'Terminal: Select Default Shell', category); -} -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(AllowWorkspaceShellTerminalCommand, AllowWorkspaceShellTerminalCommand.ID, AllowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Allow Workspace Shell Configuration', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DisallowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand.ID, DisallowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Disallow Workspace Shell Configuration', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.KEY_F -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.KEY_F -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, { - primary: KeyCode.Escape, - secondary: [KeyMod.Shift | KeyCode.Escape] -}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE)), 'Terminal: Hide Find Widget', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteWordLeftTerminalAction, DeleteWordLeftTerminalAction.ID, DeleteWordLeftTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.Backspace, - mac: { primary: KeyMod.Alt | KeyCode.Backspace } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Left', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteWordRightTerminalAction, DeleteWordRightTerminalAction.ID, DeleteWordRightTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.Delete, - mac: { primary: KeyMod.Alt | KeyCode.Delete } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Right', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteToLineStartTerminalAction, DeleteToLineStartTerminalAction.ID, DeleteToLineStartTerminalAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete To Line Start', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(MoveToLineStartTerminalAction, MoveToLineStartTerminalAction.ID, MoveToLineStartTerminalAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.LeftArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line Start', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(MoveToLineEndTerminalAction, MoveToLineEndTerminalAction.ID, MoveToLineEndTerminalAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.RightArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line End', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH, - secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_5], - mac: { - primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH, - secondary: [KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_5] - } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitInActiveWorkspaceTerminalAction, SplitInActiveWorkspaceTerminalAction.ID, SplitInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Split Terminal (In Active Workspace)', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, { - primary: KeyMod.Alt | KeyCode.LeftArrow, - secondary: [KeyMod.Alt | KeyCode.UpArrow], - mac: { - primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.LeftArrow, - secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.UpArrow] - } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Previous Pane', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTerminalAction, FocusNextPaneTerminalAction.ID, FocusNextPaneTerminalAction.LABEL, { - primary: KeyMod.Alt | KeyCode.RightArrow, - secondary: [KeyMod.Alt | KeyCode.DownArrow], - mac: { - primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.RightArrow, - secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.DownArrow] - } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Next Pane', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, { - primary: 0, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow }, - mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Left', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, { - primary: 0, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow }, - mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Right', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, { - primary: 0, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, - mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.UpArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Up', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, { - primary: 0, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }, - mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.DownArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Down', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToPreviousCommandAction, ScrollToPreviousCommandAction.ID, ScrollToPreviousCommandAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Previous Command', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToNextCommandAction, ScrollToNextCommandAction.ID, ScrollToNextCommandAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Next Command', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousCommandAction, SelectToPreviousCommandAction.ID, SelectToPreviousCommandAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Previous Command', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextCommandAction, SelectToNextCommandAction.ID, SelectToNextCommandAction.LABEL, { - primary: 0, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Next Command', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_R, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find by regex'); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID_TERMINAL_FOCUS, ToggleRegexCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_R, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find by regex', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_W, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find whole word'); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID_TERMINAL_FOCUS, ToggleWholeWordCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_W, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find whole word', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_C, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find match case'); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID_TERMINAL_FOCUS, ToggleCaseSensitiveCommand.LABEL, { - primary: KeyMod.Alt | KeyCode.KEY_C, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find match case', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID_TERMINAL_FOCUS, FindNext.LABEL, { - primary: KeyCode.F3, - mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] } -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find next', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID, FindNext.LABEL, { - primary: KeyCode.F3, - mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] } -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find next'); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID_TERMINAL_FOCUS, FindPrevious.LABEL, { - primary: KeyMod.Shift | KeyCode.F3, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] }, -}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find previous', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID, FindPrevious.LABEL, { - primary: KeyMod.Shift | KeyCode.F3, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] }, -}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find previous'); - - -const sendSequenceTerminalCommand = new SendSequenceTerminalCommand({ - id: SendSequenceTerminalCommand.ID, - precondition: null, - description: { - description: `Send Custom Sequence To Terminal`, - args: [{ - name: 'args', - schema: { - 'type': 'object', - 'required': ['text'], - 'properties': { - 'text': { - 'type': 'string' - } - }, - } - }] - } -}); -sendSequenceTerminalCommand.register(); - -setupTerminalCommands(); -setupTerminalMenu(); - -registerColors(); diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 84ed6ce8f02..69bf6bcd8ce 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -152,6 +152,7 @@ import 'vs/workbench/contrib/output/electron-browser/output.contribution'; import 'vs/workbench/contrib/output/browser/outputPanel'; // Terminal +import 'vs/workbench/contrib/terminal/browser/terminal.contribution'; import 'vs/workbench/contrib/terminal/electron-browser/terminal.contribution'; import 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; import 'vs/workbench/contrib/terminal/browser/terminalPanel'; From 31f6902afdc791513bb57f3fc4d9cf5aac2f7b8e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 09:42:23 +0100 Subject: [PATCH 031/172] exploration - auto release after build --- build/azure-pipelines/common/publish.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/azure-pipelines/common/publish.ts b/build/azure-pipelines/common/publish.ts index 2095c2d2532..ef17c3fd685 100644 --- a/build/azure-pipelines/common/publish.ts +++ b/build/azure-pipelines/common/publish.ts @@ -152,9 +152,13 @@ async function publish(commit: string, quality: string, platform: string, type: const queuedBy = process.env['BUILD_QUEUEDBY']!; const sourceBranch = process.env['BUILD_SOURCEBRANCH']!; - const isReleased = quality === 'insider' - && /^master$|^refs\/heads\/master$/.test(sourceBranch) - && /Project Collection Service Accounts|Microsoft.VisualStudio.Services.TFS/.test(queuedBy); + const isReleased = ( + // Insiders: nightly build from master + (quality === 'insider' && /^master$|^refs\/heads\/master$/.test(sourceBranch) && /Project Collection Service Accounts|Microsoft.VisualStudio.Services.TFS/.test(queuedBy)) || + + // Exploration: any build from electron-4.0.x branch + (quality === 'exploration' && /^electron-4.0.x$|^refs\/heads\/electron-4.0.x$/.test(sourceBranch)) + ); console.log('Publishing...'); console.log('Quality:', quality); From 3f68665c306be9a04decb12f2bbbc51b5317190a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 09:39:45 +0100 Subject: [PATCH 032/172] strict null - contrib/outline --- src/tsconfig.strictNullChecks.json | 2 +- src/vs/workbench/contrib/outline/browser/outlinePanel.ts | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 8d70756d2f6..1c3308561b0 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -16,6 +16,7 @@ "./vs/workbench/contrib/emmet/**/*", "./vs/workbench/contrib/externalTerminal/**/*", "./vs/workbench/contrib/snippets/**/*.ts", + "./vs/workbench/contrib/outline/**/*.ts", "./vs/workbench/contrib/welcome/**/*.ts", "./vs/workbench/contrib/issue/**/*", "./vs/workbench/contrib/tasks/**/*.ts", @@ -277,7 +278,6 @@ "./vs/workbench/contrib/stats/test/workspaceStats.test.ts", "./vs/workbench/contrib/surveys/electron-browser/languageSurveys.contribution.ts", "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", - "./vs/workbench/contrib/terminal/browser/terminalActions.ts", "./vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts", "./vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts", diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index 86d3df7c5ea..d6d2c3f39fc 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -47,6 +47,7 @@ import { OutlineDataSource, OutlineItemComparator, OutlineSortOrder, OutlineVirt import { IDataTreeViewState } from 'vs/base/browser/ui/tree/dataTree'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { basename } from 'vs/base/common/resources'; +import { IDataSource } from 'vs/base/browser/ui/tree/tree'; class RequestState { @@ -320,7 +321,7 @@ export class OutlinePanel extends ViewletPanel { treeContainer, new OutlineVirtualDelegate(), [new OutlineGroupRenderer(), this._treeRenderer], - this._treeDataSource, + this._treeDataSource as IDataSource, { expandOnlyOnTwistieClick: true, multipleSelectionSupport: false, @@ -342,7 +343,7 @@ export class OutlinePanel extends ViewletPanel { // feature: filter on type - keep tree and menu in sync this.disposables.push(this._tree.onDidUpdateOptions(e => { - this._outlineViewState.filterOnType = e.filterOnType; + this._outlineViewState.filterOnType = Boolean(e.filterOnType); })); // feature: expand all nodes when filtering (not when finding) @@ -355,7 +356,7 @@ export class OutlinePanel extends ViewletPanel { viewState = this._tree.getViewState(); this._tree.expandAll(); } else if (!pattern && viewState) { - this._tree.setInput(this._tree.getInput(), viewState); + this._tree.setInput(this._tree.getInput()!, viewState); viewState = undefined; } })); @@ -426,7 +427,7 @@ export class OutlinePanel extends ViewletPanel { private _showMessage(message: string) { dom.addClass(this._domNode, 'message'); - this._tree.setInput(undefined); + this._tree.setInput(undefined!); this._progressBar.stop().hide(); this._message.innerText = escape(message); } From 105f4f84fbe7770a0abcc13816525bfaf904f5b9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 09:45:28 +0100 Subject: [PATCH 033/172] more strict null --- src/tsconfig.strictNullChecks.json | 15 ++++++--------- .../services/progress/browser/progressService2.ts | 8 +++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 1c3308561b0..bd09c3b049a 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -17,12 +17,17 @@ "./vs/workbench/contrib/externalTerminal/**/*", "./vs/workbench/contrib/snippets/**/*.ts", "./vs/workbench/contrib/outline/**/*.ts", + "./vs/workbench/contrib/performance/**/*.ts", "./vs/workbench/contrib/welcome/**/*.ts", "./vs/workbench/contrib/issue/**/*", + "./vs/workbench/contrib/splash/**/*.ts", "./vs/workbench/contrib/tasks/**/*.ts", "./vs/workbench/services/commands/**/*", "./vs/workbench/services/files/node/watcher/**/*", - "./vs/workbench/services/themes/**/*.ts" + "./vs/workbench/services/themes/**/*.ts", + "./vs/workbench/services/bulkEdit/**/*.ts", + "./vs/workbench/services/progress/**/*.ts", + "./vs/workbench/services/timer/**/*.ts" ], "files": [ "./vs/monaco.d.ts", @@ -237,9 +242,6 @@ "./vs/workbench/contrib/output/common/outputLinkComputer.ts", "./vs/workbench/contrib/output/common/outputLinkProvider.ts", "./vs/workbench/contrib/output/node/outputAppender.ts", - "./vs/workbench/contrib/performance/electron-browser/perfviewEditor.ts", - "./vs/workbench/contrib/performance/electron-browser/startupProfiler.ts", - "./vs/workbench/contrib/performance/electron-browser/startupTimings.ts", "./vs/workbench/contrib/preferences/browser/settingsWidgets.ts", "./vs/workbench/contrib/preferences/common/smartSnippetInserter.ts", "./vs/workbench/contrib/preferences/test/common/smartSnippetInserter.test.ts", @@ -272,7 +274,6 @@ "./vs/workbench/contrib/search/test/browser/openFileHandler.test.ts", "./vs/workbench/contrib/search/test/common/searchModel.test.ts", "./vs/workbench/contrib/search/test/common/searchResult.test.ts", - "./vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts", "./vs/workbench/contrib/stats/node/stats.contribution.ts", "./vs/workbench/contrib/stats/node/workspaceStats.ts", "./vs/workbench/contrib/stats/test/workspaceStats.test.ts", @@ -313,7 +314,6 @@ "./vs/workbench/services/backup/common/backup.ts", "./vs/workbench/services/backup/node/backupFileService.ts", "./vs/workbench/services/broadcast/electron-browser/broadcastService.ts", - "./vs/workbench/services/bulkEdit/browser/bulkEditService.ts", "./vs/workbench/services/configuration/common/configuration.ts", "./vs/workbench/services/configuration/common/configurationModels.ts", "./vs/workbench/services/configuration/common/jsonEditing.ts", @@ -373,8 +373,6 @@ "./vs/workbench/services/part/common/partService.ts", "./vs/workbench/services/preferences/common/keybindingsEditorModel.ts", "./vs/workbench/services/preferences/test/common/keybindingsEditorModel.test.ts", - "./vs/workbench/services/progress/browser/progressService.ts", - "./vs/workbench/services/progress/test/progressService.test.ts", "./vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts", "./vs/workbench/services/remote/node/remoteAgentEnvironmentChannel.ts", "./vs/workbench/services/remote/node/remoteAgentService.ts", @@ -409,7 +407,6 @@ "./vs/workbench/services/textfile/common/textFileEditorModelManager.ts", "./vs/workbench/services/textfile/common/textfiles.ts", "./vs/workbench/services/textfile/node/textResourcePropertiesService.ts", - "./vs/workbench/services/timer/electron-browser/timerService.ts", "./vs/workbench/services/title/common/titleService.ts", "./vs/workbench/services/viewlet/browser/viewlet.ts", "./vs/workbench/services/workspace/common/workspaceEditing.ts", diff --git a/src/vs/workbench/services/progress/browser/progressService2.ts b/src/vs/workbench/services/progress/browser/progressService2.ts index f61446ca4b9..d267ae05770 100644 --- a/src/vs/workbench/services/progress/browser/progressService2.ts +++ b/src/vs/workbench/services/progress/browser/progressService2.ts @@ -39,8 +39,7 @@ export class ProgressService2 implements IProgressService2 { if (viewlet) { return this._withViewletProgress(location, task); } - console.warn(`Bad progress location: ${location}`); - return undefined; + return Promise.reject(new Error(`Bad progress location: ${location}`)); } switch (location) { @@ -55,8 +54,7 @@ export class ProgressService2 implements IProgressService2 { case ProgressLocation.Extensions: return this._withViewletProgress('workbench.view.extensions', task); default: - console.warn(`Bad progress location: ${location}`); - return undefined; + return Promise.reject(new Error(`Bad progress location: ${location}`)); } } @@ -269,4 +267,4 @@ export class ProgressService2 implements IProgressService2 { } } -registerSingleton(IProgressService2, ProgressService2, true); \ No newline at end of file +registerSingleton(IProgressService2, ProgressService2, true); From 4e3dcb718bff1a64bc2377e045c1b12eec5cc640 Mon Sep 17 00:00:00 2001 From: "Ryan A. Pavlik" Date: Tue, 5 Mar 2019 02:47:09 -0600 Subject: [PATCH 034/172] Update preferences.contribution.ts (#69807) Fix typo in spelling of Preferences. --- .../electron-browser/preferences.contribution.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/electron-browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/electron-browser/preferences.contribution.ts index 6d2d5ab3bc1..e9af73dc862 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/preferences.contribution.ts @@ -477,7 +477,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: OpenFolderSettingsAction.ID, title: { value: `${category}: ${OpenFolderSettingsAction.LABEL}`, original: 'Preferences: Open Folder Settings' }, - category: nls.localize('preferencesCategory', "Prefernces") + category: nls.localize('preferencesCategory', "Preferences") }, when: WorkbenchStateContext.isEqualTo('workspace') }); @@ -489,7 +489,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: OpenWorkspaceSettingsAction.ID, title: { value: `${category}: ${OpenWorkspaceSettingsAction.LABEL}`, original: 'Preferences: Open Workspace Settings' }, - category: nls.localize('preferencesCategory', "Prefernces") + category: nls.localize('preferencesCategory', "Preferences") }, when: WorkbenchStateContext.notEqualsTo('empty') }); @@ -799,4 +799,4 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { title: OPEN_FOLDER_SETTINGS_LABEL }, when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext) -}); \ No newline at end of file +}); From 10cd21c637ecbe267a2c5cfa53d1ea008790388a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 10:08:56 +0100 Subject: [PATCH 035/172] better error message for #68744 --- src/vs/code/electron-main/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index f89af11d2aa..d3d8f3fa86d 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -216,7 +216,7 @@ function handleStartupDataDirError(environmentService: IEnvironmentService, erro if (error.code === 'EACCES' || error.code === 'EPERM') { showStartupWarningDialog( localize('startupDataDirError', "Unable to write program user data."), - localize('startupDataDirErrorDetail', "Please make sure the directory {0} is writeable.", environmentService.userDataPath) + localize('startupDataDirErrorDetail', "Please make sure the directories {0} and {1} are writeable.", environmentService.userDataPath, environmentService.extensionsPath) ); } } From 1eb6de1daf76b118eb21296afcc4afd248e6fda1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 10:00:20 +0100 Subject: [PATCH 036/172] clean up some todos --- extensions/git/src/decorationProvider.ts | 1 - extensions/git/src/repository.ts | 2 +- src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts | 1 - src/vs/workbench/contrib/outline/browser/outlinePanel.ts | 3 +-- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 97a6a41997f..9f17b20ee8e 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -20,7 +20,6 @@ class GitIgnoreDecorationProvider implements DecorationProvider { private disposables: Disposable[] = []; constructor(private model: Model) { - //todo@joh -> events when the ignore status actually changes, not only when the file changes this.onDidChangeDecorations = fireEvent(anyEvent( filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore')), model.onDidOpenRepository, diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 388a1f28043..2fac9e2a39f 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -206,7 +206,7 @@ export class Resource implements SourceControlResourceState { case Status.INDEX_ADDED: case Status.INTENT_TO_ADD: return new ThemeColor('gitDecoration.addedResourceForeground'); - case Status.INDEX_RENAMED: // todo@joh - special color? + case Status.INDEX_RENAMED: case Status.UNTRACKED: return new ThemeColor('gitDecoration.untrackedResourceForeground'); case Status.IGNORED: diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index 731a9309798..065e9e61a48 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -169,7 +169,6 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic return this._mainThreadEditors.$tryApplyWorkspaceEdit({ edits: [resourceEdit] }); } - // TODO@joh bubble this to listener? return Promise.reject(new Error('concurrent_edits')); }); } diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index d6d2c3f39fc..59dbfe4c344 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -335,8 +335,7 @@ export class OutlinePanel extends ViewletPanel { this._disposables.push(this._tree); this._disposables.push(this._outlineViewState.onDidChange(this._onDidChangeUserState, this)); - // todo@joh workaournd for the tree resetting the filter behaviour - // to something globally defined + // override the globally defined behaviour this._tree.updateOptions({ filterOnType: this._outlineViewState.filterOnType }); From de8f1b8025cb20bf03b936102aba1a7ed56163d1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 10:15:51 +0100 Subject: [PATCH 037/172] reset editor selection when explicitly cancelling snippet mode, #68512 --- .../contrib/snippet/snippetController2.ts | 10 ++++- .../snippet/test/snippetController2.test.ts | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index febc52c54a6..42ff4261198 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -193,7 +193,7 @@ export class SnippetController2 implements IEditorContribution { } } - cancel(): void { + cancel(resetSelection: boolean = false): void { this._inSnippet.reset(); this._hasPrevTabstop.reset(); this._hasNextTabstop.reset(); @@ -201,6 +201,12 @@ export class SnippetController2 implements IEditorContribution { dispose(this._session); this._session = undefined; this._modelVersionId = -1; + if (resetSelection) { + // reset selection to the primary cursor when being asked + // for. this happens when explicitly cancelling snippet mode, + // e.g. when pressing ESC + this._editor.setSelections([this._editor.getSelection()]); + } } prev(): void { @@ -257,7 +263,7 @@ registerEditorCommand(new CommandCtor({ registerEditorCommand(new CommandCtor({ id: 'leaveSnippet', precondition: SnippetController2.InSnippetMode, - handler: ctrl => ctrl.cancel(), + handler: ctrl => ctrl.cancel(true), kbOpts: { weight: KeybindingWeight.EditorContrib + 30, kbExpr: EditorContextKeys.editorTextFocus, diff --git a/src/vs/editor/contrib/snippet/test/snippetController2.test.ts b/src/vs/editor/contrib/snippet/test/snippetController2.test.ts index 668fc0b74b9..95395786fd0 100644 --- a/src/vs/editor/contrib/snippet/test/snippetController2.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetController2.test.ts @@ -361,4 +361,44 @@ suite('SnippetController2', function () { assertSelections(editor, new Selection(1, 7, 1, 7)); assertContextKeys(contextKeys, false, false, false); }); + + test('Cancelling snippet mode should discard added cursors #68512 (soft cancel)', function () { + const ctrl = new SnippetController2(editor, logService, contextKeys); + model.setValue(''); + editor.setSelection(new Selection(1, 1, 1, 1)); + + ctrl.insert('.REGION ${2:FUNCTION_NAME}\nCREATE.FUNCTION ${1:VOID} ${2:FUNCTION_NAME}(${3:})\n\t${4:}\nEND\n.ENDREGION$0'); + assertSelections(editor, new Selection(2, 17, 2, 21)); + + ctrl.next(); + assertSelections(editor, new Selection(1, 9, 1, 22), new Selection(2, 22, 2, 35)); + assertContextKeys(contextKeys, true, true, true); + + editor.setSelections([new Selection(1, 22, 1, 22), new Selection(2, 35, 2, 35)]); + assertContextKeys(contextKeys, true, true, true); + + editor.setSelections([new Selection(2, 1, 2, 1), new Selection(2, 36, 2, 36)]); + assertContextKeys(contextKeys, false, false, false); + assertSelections(editor, new Selection(2, 1, 2, 1), new Selection(2, 36, 2, 36)); + }); + + test('Cancelling snippet mode should discard added cursors #68512 (hard cancel)', function () { + const ctrl = new SnippetController2(editor, logService, contextKeys); + model.setValue(''); + editor.setSelection(new Selection(1, 1, 1, 1)); + + ctrl.insert('.REGION ${2:FUNCTION_NAME}\nCREATE.FUNCTION ${1:VOID} ${2:FUNCTION_NAME}(${3:})\n\t${4:}\nEND\n.ENDREGION$0'); + assertSelections(editor, new Selection(2, 17, 2, 21)); + + ctrl.next(); + assertSelections(editor, new Selection(1, 9, 1, 22), new Selection(2, 22, 2, 35)); + assertContextKeys(contextKeys, true, true, true); + + editor.setSelections([new Selection(1, 22, 1, 22), new Selection(2, 35, 2, 35)]); + assertContextKeys(contextKeys, true, true, true); + + ctrl.cancel(true); + assertContextKeys(contextKeys, false, false, false); + assertSelections(editor, new Selection(1, 22, 1, 22)); + }); }); From 3d3450cc95c5bfbee5e07366ca70969df5d665e8 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Mar 2019 10:26:36 +0100 Subject: [PATCH 038/172] Fix #68546 --- .../node/configurationService.ts | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 1e90cfd6285..b71054c6318 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { ResourceMap } from 'vs/base/common/map'; import { equals, deepClone } from 'vs/base/common/objects'; import { Disposable } from 'vs/base/common/lifecycle'; -import { Queue } from 'vs/base/common/async'; +import { Queue, Barrier } from 'vs/base/common/async'; import { writeFile } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -35,14 +35,14 @@ import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { localize } from 'vs/nls'; import { isEqual, dirname } from 'vs/base/common/resources'; import { mark } from 'vs/base/common/performance'; +import { Schemas } from 'vs/base/common/network'; export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { public _serviceBrand: any; private workspace: Workspace; - private resolvePromise: Promise; - private resolveCallback: () => void; + private completeWorkspaceBarrier: Barrier; private _configuration: Configuration; private defaultConfiguration: DefaultConfigurationModel; private userConfiguration: UserConfiguration; @@ -70,7 +70,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat constructor(private environmentService: IEnvironmentService, private workspaceSettingsRootFolder: string = FOLDER_CONFIG_FOLDER_NAME) { super(); - this.resolvePromise = new Promise(c => this.resolveCallback = c); + this.completeWorkspaceBarrier = new Barrier(); this.defaultConfiguration = new DefaultConfigurationModel(); this.userConfiguration = this._register(new UserConfiguration(environmentService.appSettingsPath)); this.workspaceConfiguration = this._register(new WorkspaceConfiguration(environmentService)); @@ -86,7 +86,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // Workspace Context Service Impl public getCompleteWorkspace(): Promise { - return this.resolvePromise.then(() => this.getWorkspace()); + return this.completeWorkspaceBarrier.wait().then(() => this.getWorkspace()); } public getWorkspace(): Workspace { @@ -304,7 +304,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat for (const workspaceFolder of changedWorkspaceFolders) { this.onWorkspaceFolderConfigurationChanged(workspaceFolder); } - this.resolveCallback(); + this.releaseWorkspaceBarrier(); }); } @@ -331,7 +331,11 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat const workspaceConfigPath = workspaceIdentifier.configPath; const workspaceFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), dirname(workspaceConfigPath)); const workspaceId = workspaceIdentifier.id; - return new Workspace(workspaceId, workspaceFolders, workspaceConfigPath); + const workspace = new Workspace(workspaceId, workspaceFolders, workspaceConfigPath); + if (workspace.configuration.scheme === Schemas.file) { + this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is from disk. + } + return workspace; }); } @@ -345,11 +349,21 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat configuredFolders = [{ uri: folder.toString() }]; } - return Promise.resolve(new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders))); + const workspace = new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders)); + this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is single folder. + return Promise.resolve(workspace); } private createEmptyWorkspace(emptyWorkspace: IEmptyWorkspaceInitializationPayload): Promise { - return Promise.resolve(new Workspace(emptyWorkspace.id)); + const workspace = new Workspace(emptyWorkspace.id); + this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is an empty workspace. + return Promise.resolve(workspace); + } + + private releaseWorkspaceBarrier(): void { + if (!this.completeWorkspaceBarrier.isOpen()) { + this.completeWorkspaceBarrier.open(); + } } private updateWorkspaceAndInitializeConfiguration(workspace: Workspace, postInitialisationTask: () => void): Promise { From e5d9409ab7b6cfe345af20435db423415f956bba Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 10:26:49 +0100 Subject: [PATCH 039/172] undo aria change --- src/vs/base/browser/ui/aria/aria.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/vs/base/browser/ui/aria/aria.ts b/src/vs/base/browser/ui/aria/aria.ts index d7dad9cba5c..1922450144d 100644 --- a/src/vs/base/browser/ui/aria/aria.ts +++ b/src/vs/base/browser/ui/aria/aria.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./aria'; +import * as nls from 'vs/nls'; import { isMacintosh } from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; @@ -47,12 +48,29 @@ export function status(msg: string): void { } } +let repeatedTimes = 0; +let prevText: string | undefined = undefined; function insertMessage(target: HTMLElement, msg: string): void { if (!ariaContainer) { // console.warn('ARIA support needs a container. Call setARIAContainer() first.'); return; } + if (prevText === msg) { + repeatedTimes++; + } + else { + prevText = msg; + repeatedTimes = 0; + } + + + switch (repeatedTimes) { + case 0: break; + case 1: msg = nls.localize('repeated', "{0} (occurred again)", msg); break; + default: msg = nls.localize('repeatedNtimes', "{0} (occurred {1} times)", msg, repeatedTimes); break; + } + dom.clearNode(target); target.textContent = msg; From 809297c9cf762dabf296f66775a3d95238c3c15c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 10:31:31 +0100 Subject: [PATCH 040/172] only alert when inserting a suggestion make additional editor, like inserting an import statement, simplify the message that read when selecting an item --- .../editor/contrib/suggest/suggestController.ts | 7 +++++-- src/vs/editor/contrib/suggest/suggestWidget.ts | 16 +++------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 20f37c560e0..c471b0fe568 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { alert } from 'vs/base/browser/ui/aria/aria'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; @@ -291,8 +292,10 @@ export class SuggestController implements IEditorContribution { } private _alertCompletionItem({ completion: suggestion }: CompletionItem): void { - // A temporary fix for too verbose, unnecesary screen reader alerts. - // Todo: Remove calls to this empty method body. + if (isNonEmptyArray(suggestion.additionalTextEdits)) { + let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' made {1} additional edits", suggestion.label, suggestion.additionalTextEdits.length); + alert(msg); + } } triggerSuggest(onlyFrom?: CompletionItemProvider[]): void { diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 8de80617e8d..13e51c949d9 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -540,20 +540,10 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate Date: Tue, 5 Mar 2019 10:33:26 +0100 Subject: [PATCH 041/172] debt - IActiveTextEditorModel => IResolvedTextEditorModel --- src/vs/editor/common/services/resolverService.ts | 8 ++++++-- src/vs/editor/standalone/browser/simpleServices.ts | 6 +++--- src/vs/workbench/common/editor/textEditorModel.ts | 4 ++-- .../services/bulkEdit/browser/bulkEditService.ts | 6 +++--- .../services/configuration/node/jsonEditingService.ts | 10 +++++----- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/common/services/resolverService.ts b/src/vs/editor/common/services/resolverService.ts index 2b04d4b1218..ef65b34685e 100644 --- a/src/vs/editor/common/services/resolverService.ts +++ b/src/vs/editor/common/services/resolverService.ts @@ -18,7 +18,7 @@ export interface ITextModelService { * Provided a resource URI, it will return a model reference * which should be disposed once not needed anymore. */ - createModelReference(resource: URI): Promise>; + createModelReference(resource: URI): Promise>; /** * Registers a specific `scheme` content provider. @@ -49,6 +49,10 @@ export interface ITextEditorModel extends IEditorModel { isReadonly(): boolean; } -export interface IActiveTextEditorModel extends ITextEditorModel { +export interface IResolvedTextEditorModel extends ITextEditorModel { + + /** + * Same as ITextEditorModel#textEditorModel, but never null. + */ readonly textEditorModel: ITextModel; } diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 7c6487339f2..c76b38b22df 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -22,7 +22,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { TextEdit, WorkspaceEdit, isResourceTextEdit } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { IActiveTextEditorModel, ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IResolvedTextEditorModel, ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; import { CommandsRegistry, ICommand, ICommandEvent, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -44,7 +44,7 @@ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFolde import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; -export class SimpleModel implements IActiveTextEditorModel { +export class SimpleModel implements IResolvedTextEditorModel { private model: ITextModel; private readonly _onDispose: Emitter; @@ -98,7 +98,7 @@ export class SimpleEditorModelResolverService implements ITextModelService { this.editor = editor; } - public createModelReference(resource: URI): Promise> { + public createModelReference(resource: URI): Promise> { let model: ITextModel | null = withTypedEditor(this.editor, (editor) => this.findModel(editor, resource), (diffEditor) => this.findModel(diffEditor.getOriginalEditor(), resource) || this.findModel(diffEditor.getModifiedEditor(), resource) diff --git a/src/vs/workbench/common/editor/textEditorModel.ts b/src/vs/workbench/common/editor/textEditorModel.ts index b8279be7d5c..4ba0027e985 100644 --- a/src/vs/workbench/common/editor/textEditorModel.ts +++ b/src/vs/workbench/common/editor/textEditorModel.ts @@ -6,7 +6,7 @@ import { ITextModel, ITextBufferFactory } from 'vs/editor/common/model'; import { EditorModel } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; -import { ITextEditorModel, IActiveTextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -135,7 +135,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd return null; } - isResolved(): this is IActiveTextEditorModel { + isResolved(): this is IResolvedTextEditorModel { return !!this.textEditorModelHandle; } diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index 93494c3bbc7..5137f89c2c5 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -13,7 +13,7 @@ import { Range } from 'vs/editor/common/core/range'; import { EndOfLineSequence, IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model'; import { isResourceFileEdit, isResourceTextEdit, ResourceFileEdit, ResourceTextEdit, WorkspaceEdit } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { ITextModelService, IActiveTextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { localize } from 'vs/nls'; import { IFileService } from 'vs/platform/files/common/files'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -53,7 +53,7 @@ class ModelEditTask implements IDisposable { private _expectedModelVersionId: number | undefined; protected _newEol: EndOfLineSequence; - constructor(private readonly _modelReference: IReference) { + constructor(private readonly _modelReference: IReference) { this._model = this._modelReference.object.textEditorModel; this._edits = []; } @@ -115,7 +115,7 @@ class EditorEditTask extends ModelEditTask { private _editor: ICodeEditor; - constructor(modelReference: IReference, editor: ICodeEditor) { + constructor(modelReference: IReference, editor: ICodeEditor) { super(modelReference); this._editor = editor; } diff --git a/src/vs/workbench/services/configuration/node/jsonEditingService.ts b/src/vs/workbench/services/configuration/node/jsonEditingService.ts index e8f1ab3be9b..5c08f612786 100644 --- a/src/vs/workbench/services/configuration/node/jsonEditingService.ts +++ b/src/vs/workbench/services/configuration/node/jsonEditingService.ts @@ -17,7 +17,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IFileService } from 'vs/platform/files/common/files'; -import { ITextModelService, IActiveTextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IJSONEditingService, IJSONValue, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing'; import { ITextModel } from 'vs/editor/common/model'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -84,7 +84,7 @@ export class JSONEditingService implements IJSONEditingService { return setProperty(model.getValue(), [key], value, { tabSize, insertSpaces, eol }); } - private async resolveModelReference(resource: URI): Promise> { + private async resolveModelReference(resource: URI): Promise> { const exists = await this.fileService.existsFile(resource); if (!exists) { await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 }); @@ -98,18 +98,18 @@ export class JSONEditingService implements IJSONEditingService { return parseErrors.length > 0; } - private resolveAndValidate(resource: URI, checkDirty: boolean): Promise> { + private resolveAndValidate(resource: URI, checkDirty: boolean): Promise> { return this.resolveModelReference(resource) .then(reference => { const model = reference.object.textEditorModel; if (this.hasParseErrors(model)) { - return this.reject>(JSONEditingErrorCode.ERROR_INVALID_FILE); + return this.reject>(JSONEditingErrorCode.ERROR_INVALID_FILE); } // Target cannot be dirty if not writing into buffer if (checkDirty && this.textFileService.isDirty(resource)) { - return this.reject>(JSONEditingErrorCode.ERROR_FILE_DIRTY); + return this.reject>(JSONEditingErrorCode.ERROR_FILE_DIRTY); } return reference; }); From e1dac9dee155604f2dc76ab20e53767691eca95e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 10:36:05 +0100 Subject: [PATCH 042/172] files - do not focus explorer when revealing folder (for #69333) --- .../workbench/contrib/files/browser/editors/textFileEditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 5e1a9623ea0..c5c6bcb72ca 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -234,7 +234,7 @@ export class TextFileEditor extends BaseTextEditor { // Best we can do is to reveal the folder in the explorer if (this.contextService.isInsideWorkspace(input.getResource())) { - this.viewletService.openViewlet(VIEWLET_ID, true).then(() => { + this.viewletService.openViewlet(VIEWLET_ID).then(() => { this.explorerService.select(input.getResource(), true); }); } From 0bb3bfc4b4ffe6d94cc67fbd712b706d4250f3ff Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 10:38:07 +0100 Subject: [PATCH 043/172] strict null trouble --- src/vs/editor/contrib/snippet/snippetController2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index 42ff4261198..3f87729b6ab 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -205,7 +205,7 @@ export class SnippetController2 implements IEditorContribution { // reset selection to the primary cursor when being asked // for. this happens when explicitly cancelling snippet mode, // e.g. when pressing ESC - this._editor.setSelections([this._editor.getSelection()]); + this._editor.setSelections([this._editor.getSelection()!]); } } From 4f197a7079bf2ce1346db1739f8b89cd700d079f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 5 Mar 2019 10:41:16 +0100 Subject: [PATCH 044/172] :lipstick: --- extensions/git/src/commands.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 165895701b6..8e798b0cc77 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -649,17 +649,16 @@ export class CommandCenter { if (!(resource instanceof Resource)) { // can happen when called from a keybinding + console.log('WHAT'); resource = this.getSCMResource(); } if (resource) { - const resources = ([resource, ...resourceStates] as Resource[]) - .filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED); - - uris = resources.map(r => r.resourceUri); - } - else { - uris = [(window.activeTextEditor && window.activeTextEditor.document.uri)] as Uri[]; + uris = ([resource, ...resourceStates] as Resource[]) + .filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED) + .map(r => r.resourceUri); + } else if (window.activeTextEditor) { + uris = [window.activeTextEditor.document.uri]; } } @@ -668,6 +667,7 @@ export class CommandCenter { } const activeTextEditor = window.activeTextEditor; + for (const uri of uris) { const opts: TextDocumentShowOptions = { preserveFocus, @@ -2120,6 +2120,7 @@ export class CommandCenter { uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri); this.outputChannel.appendLine(`git.getSCMResource.uri ${uri && uri.toString()}`); + for (const r of this.model.repositories.map(r => r.root)) { this.outputChannel.appendLine(`repo root ${r}`); } From 8f0c07ac9ea547821461a1f6e90044beffe1a030 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Mar 2019 10:44:22 +0100 Subject: [PATCH 045/172] Get rid of editable map, it should not be a map but just one element fixes #69531 --- .../contrib/files/browser/media/explorerviewlet.css | 4 ++-- .../contrib/files/browser/views/explorerView.ts | 4 ++-- .../workbench/contrib/files/common/explorerService.ts | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css index a0c0f8de7f4..17b272cef79 100644 --- a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css @@ -18,8 +18,8 @@ padding-left: 4px; /* align top level twistie with `Explorer` title label */ } -.explorer-viewlet .monaco-list.highlight .explorer-item:not(.explorer-item-edited), -.explorer-viewlet .monaco-list.highlight .monaco-tl-twistie { +.explorer-viewlet .explorer-folders-view.highlight .monaco-list .explorer-item:not(.explorer-item-edited), +.explorer-viewlet .explorer-folders-view.highlight .monaco-list .monaco-tl-twistie { opacity: 0.3; } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 69a8b7bb575..94c206c6ebf 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -176,13 +176,13 @@ export class ExplorerView extends ViewletPanel { if (isEditing) { await this.tree.expand(e.parent); } else { - DOM.removeClass(this.tree.getHTMLElement(), 'highlight'); + DOM.removeClass(treeContainer, 'highlight'); } await this.refresh(e.parent); if (isEditing) { - DOM.addClass(this.tree.getHTMLElement(), 'highlight'); + DOM.addClass(treeContainer, 'highlight'); this.tree.reveal(e); } else { this.tree.domFocus(); diff --git a/src/vs/workbench/contrib/files/common/explorerService.ts b/src/vs/workbench/contrib/files/common/explorerService.ts index 980c9b14035..7ce193360b2 100644 --- a/src/vs/workbench/contrib/files/common/explorerService.ts +++ b/src/vs/workbench/contrib/files/common/explorerService.ts @@ -37,7 +37,7 @@ export class ExplorerService implements IExplorerService { private _onDidSelectItem = new Emitter<{ item?: ExplorerItem, reveal?: boolean }>(); private _onDidCopyItems = new Emitter<{ items: ExplorerItem[], cut: boolean, previouslyCutItems: ExplorerItem[] | undefined }>(); private disposables: IDisposable[] = []; - private editableStats = new Map(); + private editable: { stat: ExplorerItem, data: IEditableData } | undefined; private _sortOrder: SortOrder; private cutItems: ExplorerItem[] | undefined; @@ -112,11 +112,10 @@ export class ExplorerService implements IExplorerService { setEditable(stat: ExplorerItem, data: IEditableData | null): void { if (!data) { - this.editableStats.delete(stat); + this.editable = undefined; } else { - this.editableStats.set(stat, data); + this.editable = { stat, data }; } - this._onDidChangeEditable.fire(stat); } @@ -133,11 +132,11 @@ export class ExplorerService implements IExplorerService { } getEditableData(stat: ExplorerItem): IEditableData | undefined { - return this.editableStats.get(stat); + return this.editable && this.editable.stat === stat ? this.editable.data : undefined; } isEditable(stat: ExplorerItem): boolean { - return this.editableStats.has(stat); + return !!this.editable && this.editable.stat === stat; } select(resource: URI, reveal?: boolean): Promise { From 2b98f571453104e33306cb8637da8faf99d1a678 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 11:01:59 +0100 Subject: [PATCH 046/172] fix #67300 --- .../electron-browser/partsSplash.contribution.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 b8f8fbbf0a5..79dcaaae6d3 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -22,6 +22,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; class PartsSplash { @@ -29,6 +30,7 @@ class PartsSplash { private readonly _disposables: IDisposable[] = []; + private _didChangeTitleBarStyle: boolean; private _lastBaseTheme: string; private _lastBackground?: string; @@ -39,13 +41,18 @@ class PartsSplash { @IEnvironmentService private readonly _envService: IEnvironmentService, @IBroadcastService private readonly _broadcastService: IBroadcastService, @ILifecycleService lifecycleService: ILifecycleService, - @IEditorGroupsService editorGroupsService: IEditorGroupsService + @IEditorGroupsService editorGroupsService: IEditorGroupsService, + @IConfigurationService configService: IConfigurationService, ) { lifecycleService.when(LifecyclePhase.Restored).then(_ => this._removePartsSplash()); Event.debounce(Event.any( onDidChangeFullscreen, editorGroupsService.onDidLayout ), () => { }, 800)(this._savePartsSplash, this, this._disposables); + + configService.onDidChangeConfiguration(e => { + this._didChangeTitleBarStyle = e.affectsConfiguration('window.titleBarStyle'); + }, this, this._disposables); } dispose(): void { @@ -100,7 +107,7 @@ class PartsSplash { } private _shouldSaveLayoutInfo(): boolean { - return !isFullscreen() && !this._envService.isExtensionDevelopment; + return !isFullscreen() && !this._envService.isExtensionDevelopment && !this._didChangeTitleBarStyle; } private _removePartsSplash(): void { From fe2571f087a0f0039a2c767e5e81daf8e1eb0261 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Mar 2019 10:43:03 +0100 Subject: [PATCH 047/172] #68546 Tests --- .../configurationService.test.ts | 64 ++++++++++++++++--- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 6d45e9d1c3d..5e78dc69c52 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -140,10 +140,66 @@ suite('WorkspaceContextService - Folder', () => { test('isCurrentWorkspace() => false', () => { assert.ok(!workspaceContextService.isCurrentWorkspace(URI.file(workspaceResource + 'abc'))); }); + + test('workspace is complete', () => workspaceContextService.getCompleteWorkspace()); }); suite('WorkspaceContextService - Workspace', () => { + let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; + + setup(() => { + return setUpWorkspace(['a', 'b']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, path.join(parentDir, 'settings.json')); + const workspaceService = new WorkspaceService(environmentService); + + instantiationService = workbenchInstantiationService(); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { + workspaceService.acquireInstantiationService(instantiationService); + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.del(parentResource, os.tmpdir()); + } + return undefined; + }); + + test('workspace folders', () => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 2); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + }); + + test('getWorkbenchState()', () => { + const actual = testObject.getWorkbenchState(); + + assert.equal(actual, WorkbenchState.WORKSPACE); + }); + + + test('workspace is complete', () => testObject.getCompleteWorkspace()); + +}); + +suite('WorkspaceContextService - Workspace Editing', () => { + let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService, fileChangeEvent: Emitter = new Emitter(); setup(() => { @@ -186,14 +242,6 @@ suite('WorkspaceContextService - Workspace', () => { return undefined; }); - test('workspace folders', () => { - const actual = testObject.getWorkspace().folders; - - assert.equal(actual.length, 2); - assert.equal(path.basename(actual[0].uri.fsPath), 'a'); - assert.equal(path.basename(actual[1].uri.fsPath), 'b'); - }); - test('add folders', () => { const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]) From 94f7ae74c556f4c5407bf9bc462e6c4721641245 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 5 Mar 2019 10:47:19 +0100 Subject: [PATCH 048/172] fixes #69529 --- extensions/git/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/git/package.json b/extensions/git/package.json index 834563c3102..f858863dd7b 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1150,6 +1150,7 @@ "%config.postCommitCommand.sync%" ], "markdownDescription": "%config.postCommitCommand%", + "scope": "resource", "default": "none" }, "git.showInlineOpenFileAction": { From 20a4f36e2517d9b56075d649beed84716ec88088 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 5 Mar 2019 11:15:42 +0100 Subject: [PATCH 049/172] add workbench/contrib/scm to strict null checks fixes #69688 --- src/tsconfig.strictNullChecks.json | 3 +- src/vs/base/browser/ui/list/list.ts | 2 +- src/vs/base/browser/ui/list/listWidget.ts | 13 ++------ .../common/editor/untitledEditorInput.ts | 14 +++----- .../common/editor/untitledEditorModel.ts | 15 ++++++--- .../scm/electron-browser/scmViewlet.ts | 32 +++++++++---------- 6 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index bd09c3b049a..d8bae789a91 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -15,6 +15,7 @@ "./vs/workbench/electron-browser/actions/**/*", "./vs/workbench/contrib/emmet/**/*", "./vs/workbench/contrib/externalTerminal/**/*", + "./vs/workbench/contrib/scm/**/*.ts", "./vs/workbench/contrib/snippets/**/*.ts", "./vs/workbench/contrib/outline/**/*.ts", "./vs/workbench/contrib/performance/**/*.ts", @@ -430,4 +431,4 @@ "./typings/require-monaco.d.ts", "./vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts" ] -} +} \ No newline at end of file diff --git a/src/vs/base/browser/ui/list/list.ts b/src/vs/base/browser/ui/list/list.ts index 80dea11ee4a..42097113808 100644 --- a/src/vs/base/browser/ui/list/list.ts +++ b/src/vs/base/browser/ui/list/list.ts @@ -55,7 +55,7 @@ export interface IListContextMenuEvent { browserEvent: UIEvent; element: T | undefined; index: number | undefined; - anchor: HTMLElement | { x: number; y: number; } | undefined; + anchor: HTMLElement | { x: number; y: number; }; } export interface IIdentityProvider { diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index cd7312809c6..197fcb2ab98 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -1127,13 +1127,7 @@ export class List implements ISpliceable, IDisposable { .map(e => new StandardKeyboardEvent(e)) .filter(e => this.didJustPressContextMenuKey = e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10)) .filter(e => { e.preventDefault(); e.stopPropagation(); return false; }) - .map(event => { - const index = this.getFocus()[0]; - const element = this.view.element(index); - const anchor = this.view.domElement(index) || undefined; - return { index, element, anchor, browserEvent: event.browserEvent }; - }) - .event; + .event as Event; const fromKeyup = Event.chain(domEvent(this.view.domNode, 'keyup')) .filter(() => { @@ -1141,14 +1135,13 @@ export class List implements ISpliceable, IDisposable { this.didJustPressContextMenuKey = false; return didJustPressContextMenuKey; }) - .filter(() => this.getFocus().length > 0) + .filter(() => this.getFocus().length > 0 && !!this.view.domElement(this.getFocus()[0])) .map(browserEvent => { const index = this.getFocus()[0]; const element = this.view.element(index); - const anchor = this.view.domElement(index) || undefined; + const anchor = this.view.domElement(index) as HTMLElement; return { index, element, anchor, browserEvent }; }) - .filter(({ anchor }) => !!anchor) .event; const fromMouse = Event.chain(this.view.onContextMenu) diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index e1800711ea6..a4fe328d79d 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -121,25 +121,21 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport return this.labelService.getUriLabel(this.resource); } - getTitle(verbosity: Verbosity): string { + getTitle(verbosity: Verbosity): string | null { if (!this.hasAssociatedFilePath) { return this.getName(); } - let title: string | undefined; switch (verbosity) { case Verbosity.SHORT: - title = this.shortTitle; - break; + return this.shortTitle; case Verbosity.MEDIUM: - title = this.mediumTitle; - break; + return this.mediumTitle; case Verbosity.LONG: - title = this.longTitle; - break; + return this.longTitle; } - return title; + return null; } isDirty(): boolean { diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 70cfc8c48e0..4d14923cc3f 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -95,7 +95,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin return this.textEditorModel.getLanguageIdentifier().language; } - return null; + return this.modeId; } getEncoding(): string { @@ -144,7 +144,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin return this.backupFileService.resolveBackupContent(backupResource); } - return null; + return undefined; }).then(backupTextBufferFactory => { const hasBackup = !!backupTextBufferFactory; @@ -171,17 +171,24 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin // Encoding this.configuredEncoding = this.configurationService.getValue(this.resource, 'files.encoding'); + // We know for a fact there is a text editor model here + const textEditorModel = this.textEditorModel!; + // Listen to content changes - this._register(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged())); + this._register(textEditorModel.onDidChangeContent(() => this.onModelContentChanged())); // Listen to mode changes - this._register(this.textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config + this._register(textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config return this; }); } private onModelContentChanged(): void { + if (!this.isResolved()) { + return; + } + this.versionId++; // mark the untitled editor as non-dirty once its content becomes empty and we do diff --git a/src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts index 077334bb5ca..39eeddba79a 100644 --- a/src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts @@ -84,11 +84,11 @@ class StatusBarAction extends Action { private commandService: ICommandService ) { super(`statusbaraction{${command.id}}`, command.title, '', true); - this.tooltip = command.tooltip; + this.tooltip = command.tooltip || ''; } run(): Promise { - return this.commandService.executeCommand(this.command.id, ...this.command.arguments); + return this.commandService.executeCommand(this.command.id, ...(this.command.arguments || [])); } } @@ -198,7 +198,7 @@ class ProviderRenderer implements IListRenderer if (icon) { template.decorationIcon.style.display = ''; template.decorationIcon.style.backgroundImage = `url('${icon}')`; - template.decorationIcon.title = resource.decorations.tooltip; + template.decorationIcon.title = resource.decorations.tooltip || ''; } else { template.decorationIcon.style.display = 'none'; template.decorationIcon.style.backgroundImage = ''; } - template.element.setAttribute('data-tooltip', resource.decorations.tooltip); + template.element.setAttribute('data-tooltip', resource.decorations.tooltip || ''); template.elementDisposable = combinedDisposable(disposables); } @@ -821,7 +821,7 @@ export class RepositoryPanel extends ViewletPanel { const validationDelayer = new ThrottledDelayer(200); const validate = () => { - return this.repository.input.validateInput(this.inputBox.value, this.inputBox.inputElement.selectionStart).then(result => { + return this.repository.input.validateInput(this.inputBox.value, this.inputBox.inputElement.selectionStart || 0).then(result => { if (!result) { this.inputBox.inputElement.removeAttribute('aria-invalid'); this.inputBox.hideMessage(); @@ -916,7 +916,7 @@ export class RepositoryPanel extends ViewletPanel { } } - layoutBody(height: number = this.cachedHeight, width: number = this.cachedWidth): void { + layoutBody(height: number | undefined = this.cachedHeight, width: number | undefined = this.cachedWidth): void { if (height === undefined) { return; } @@ -962,9 +962,9 @@ export class RepositoryPanel extends ViewletPanel { return this.menus.getTitleSecondaryActions(); } - getActionItem(action: IAction): IActionItem { + getActionItem(action: IAction): IActionItem | null { if (!(action instanceof MenuItemAction)) { - return undefined; + return null; } return new ContextAwareMenuItemActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService); @@ -1176,9 +1176,9 @@ export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewle this.onSelectionChange(this.mainPanel.getSelection()); this.mainPanelDisposable = toDisposable(() => { - this.removePanels([this.mainPanel]); + this.removePanels([this.mainPanel!]); selectionChangeDisposable.dispose(); - this.mainPanel.dispose(); + this.mainPanel!.dispose(); }); } else { this.mainPanelDisposable.dispose(); @@ -1203,7 +1203,7 @@ export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewle super.setVisible(visible); if (!visible) { - this.cachedMainPanelHeight = this.getPanelSize(this.mainPanel); + this.cachedMainPanelHeight = this.mainPanel ? this.getPanelSize(this.mainPanel) : 0; } const start = this.getContributedViewsStartIndex(); @@ -1247,9 +1247,9 @@ export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewle } } - getActionItem(action: IAction): IActionItem { + getActionItem(action: IAction): IActionItem | null { if (!(action instanceof MenuItemAction)) { - return undefined; + return null; } return new ContextAwareMenuItemActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService); @@ -1318,14 +1318,14 @@ export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewle this.removePanels(panelsToRemove); // Restore main panel height - if (this.isVisible() && typeof this.cachedMainPanelHeight === 'number') { + if (this.mainPanel && this.isVisible() && typeof this.cachedMainPanelHeight === 'number') { this.resizePanel(this.mainPanel, this.cachedMainPanelHeight); this.cachedMainPanelHeight = undefined; } // Resize all panels equally const height = typeof this.height === 'number' ? this.height : 1000; - const mainPanelHeight = this.getPanelSize(this.mainPanel); + const mainPanelHeight = this.mainPanel ? this.getPanelSize(this.mainPanel) : 0; const size = (height - mainPanelHeight - contributableViewsHeight) / repositories.length; for (const panel of this.repositoryPanels) { this.resizePanel(panel, size); From c145eedcea2ecb213992280b5c760bad50a324c9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 11:27:01 +0100 Subject: [PATCH 050/172] cancel requests when outline provider change, also retrigger request #69147 --- .../contrib/documentSymbols/outlineModel.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts index 179b23f3a11..759ea82e044 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { binarySearch, coalesceInPlace } from 'vs/base/common/arrays'; +import { binarySearch, coalesceInPlace, equals } from 'vs/base/common/arrays'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { first, forEach, size } from 'vs/base/common/collections'; import { onUnexpectedExternalError } from 'vs/base/common/errors'; @@ -266,13 +266,17 @@ export class OutlineModel extends TreeElement { static _create(textModel: ITextModel, token: CancellationToken): Promise { - let result = new OutlineModel(textModel); - let promises = DocumentSymbolProviderRegistry.ordered(textModel).map((provider, index) => { + const chainedCancellation = new CancellationTokenSource(); + token.onCancellationRequested(() => chainedCancellation.cancel()); + + const result = new OutlineModel(textModel); + const provider = DocumentSymbolProviderRegistry.ordered(textModel); + const promises = provider.map((provider, index) => { let id = TreeElement.findId(`provider_${index}`, result); let group = new OutlineGroup(id, result, provider, index); - return Promise.resolve(provider.provideDocumentSymbols(result.textModel, token)).then(result => { + return Promise.resolve(provider.provideDocumentSymbols(result.textModel, chainedCancellation.token)).then(result => { for (const info of result || []) { OutlineModel._makeOutlineElement(info, group); } @@ -289,7 +293,22 @@ export class OutlineModel extends TreeElement { }); }); - return Promise.all(promises).then(() => result._compact()); + const listener = DocumentSymbolProviderRegistry.onDidChange(() => { + const newProvider = DocumentSymbolProviderRegistry.ordered(textModel); + if (!equals(newProvider, provider)) { + chainedCancellation.cancel(); + } + }); + + return Promise.all(promises).then(() => { + if (chainedCancellation.token.isCancellationRequested && !token.isCancellationRequested) { + return OutlineModel._create(textModel, token); + } else { + return result._compact(); + } + }).finally(() => { + listener.dispose(); + }); } private static _makeOutlineElement(info: DocumentSymbol, container: OutlineGroup | OutlineElement): void { From a3ce5141e38a9d0ceb5c11eff9de65be7bc5bc06 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 5 Mar 2019 11:45:52 +0100 Subject: [PATCH 051/172] remove base64 transformation in electron IPC fixes #69338 --- .../electron-browser/ipc.electron-browser.ts | 2 +- .../ipc/electron-main/ipc.electron-main.ts | 8 +++---- src/vs/base/parts/ipc/node/ipc.electron.ts | 22 ++++--------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts b/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts index 225370373a7..055d6a54130 100644 --- a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts +++ b/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts @@ -14,7 +14,7 @@ export class Client extends IPCClient implements IDisposable { private protocol: Protocol; private static createProtocol(): Protocol { - const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'ipc:message', (_, message: string) => message); + const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'ipc:message', (_, message: Buffer) => message); ipcRenderer.send('ipc:hello'); return new Protocol(ipcRenderer, onMessage); } 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 17ae7bb81b6..f7d72041911 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 @@ -11,11 +11,11 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; interface IIPCEvent { event: { sender: Electron.WebContents; }; - message: string; + message: Buffer | null; } -function createScopedOnMessageEvent(senderId: number, eventName: string): Event { - const onMessage = Event.fromNodeEventEmitter(ipcMain, eventName, (event, message: string) => ({ event, message })); +function createScopedOnMessageEvent(senderId: number, eventName: string): Event { + const onMessage = Event.fromNodeEventEmitter(ipcMain, eventName, (event, message) => ({ event, message })); const onMessageFromSender = Event.filter(onMessage, ({ event }) => event.sender.id === senderId); return Event.map(onMessageFromSender, ({ message }) => message); } @@ -38,7 +38,7 @@ export class Server extends IPCServer { const onDidClientReconnect = new Emitter(); Server.Clients.set(id, toDisposable(() => onDidClientReconnect.fire())); - const onMessage = createScopedOnMessageEvent(id, 'ipc:message'); + const onMessage = createScopedOnMessageEvent(id, 'ipc:message') as Event; const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'ipc:disconnect')), onDidClientReconnect.event); const protocol = new Protocol(webContents, onMessage); diff --git a/src/vs/base/parts/ipc/node/ipc.electron.ts b/src/vs/base/parts/ipc/node/ipc.electron.ts index 831a27377c1..e70289747fc 100644 --- a/src/vs/base/parts/ipc/node/ipc.electron.ts +++ b/src/vs/base/parts/ipc/node/ipc.electron.ts @@ -3,33 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; -import { Event, Emitter } from 'vs/base/common/event'; - -/** - * This implementation doesn't perform well since it uses base64 encoding for buffers. - * Electron 3.0 should have suport for buffers in IPC: https://github.com/electron/electron/pull/13055 - */ +import { Event } from 'vs/base/common/event'; export interface Sender { - send(channel: string, msg: string | null): void; + send(channel: string, msg: Buffer | null): void; } export class Protocol implements IMessagePassingProtocol { - private listener: IDisposable; - - private _onMessage = new Emitter(); - get onMessage(): Event { return this._onMessage.event; } - - constructor(private sender: Sender, onMessageEvent: Event) { - onMessageEvent(msg => this._onMessage.fire(Buffer.from(msg, 'base64'))); - } + constructor(private sender: Sender, readonly onMessage: Event) { } send(message: Buffer): void { try { - this.sender.send('ipc:message', message.toString('base64')); + this.sender.send('ipc:message', message); } catch (e) { // systems are going down } @@ -37,6 +24,5 @@ export class Protocol implements IMessagePassingProtocol { dispose(): void { this.sender.send('ipc:disconnect', null); - this.listener = dispose(this.listener); } } \ No newline at end of file From 480e15ca4e755cdae84079df70eab9ca44542ac3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 5 Mar 2019 11:51:59 +0100 Subject: [PATCH 052/172] fixes #69112 --- src/tsconfig.strictNullChecks.json | 8 ++++---- .../{electron-browser => browser}/dirtydiffDecorator.ts | 0 .../{electron-browser => browser}/media/check-inverse.svg | 0 .../scm/{electron-browser => browser}/media/check.svg | 0 .../media/dirtydiffDecorator.css | 0 .../scm/{electron-browser => browser}/media/icon-dark.svg | 0 .../{electron-browser => browser}/media/icon-light.svg | 0 .../{electron-browser => browser}/media/scmViewlet.css | 0 .../scm/{electron-browser => browser}/scm.contribution.ts | 2 +- .../scm/{electron-browser => browser}/scmActivity.ts | 0 .../contrib/scm/{electron-browser => browser}/scmMenus.ts | 0 .../contrib/scm/{electron-browser => browser}/scmUtil.ts | 0 .../scm/{electron-browser => browser}/scmViewlet.ts | 0 .../test/electron-browser/colorRegistry.releaseTest.ts | 2 +- src/vs/workbench/workbench.main.ts | 4 ++-- 15 files changed, 8 insertions(+), 8 deletions(-) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/dirtydiffDecorator.ts (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/check-inverse.svg (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/check.svg (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/dirtydiffDecorator.css (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/icon-dark.svg (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/icon-light.svg (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/media/scmViewlet.css (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/scm.contribution.ts (98%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/scmActivity.ts (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/scmMenus.ts (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/scmUtil.ts (100%) rename src/vs/workbench/contrib/scm/{electron-browser => browser}/scmViewlet.ts (100%) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index d8bae789a91..7bed7f931fe 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -255,10 +255,10 @@ "./vs/workbench/contrib/relauncher/electron-browser/relauncher.contribution.ts", "./vs/workbench/contrib/scm/common/scm.ts", "./vs/workbench/contrib/scm/common/scmService.ts", - "./vs/workbench/contrib/scm/electron-browser/dirtydiffDecorator.ts", - "./vs/workbench/contrib/scm/electron-browser/scmActivity.ts", - "./vs/workbench/contrib/scm/electron-browser/scmMenus.ts", - "./vs/workbench/contrib/scm/electron-browser/scmUtil.ts", + "./vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts", + "./vs/workbench/contrib/scm/browser/scmActivity.ts", + "./vs/workbench/contrib/scm/browser/scmMenus.ts", + "./vs/workbench/contrib/scm/browser/scmUtil.ts", "./vs/workbench/contrib/search/browser/openAnythingHandler.ts", "./vs/workbench/contrib/search/browser/openFileHandler.ts", "./vs/workbench/contrib/search/browser/openSymbolHandler.ts", diff --git a/src/vs/workbench/contrib/scm/electron-browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/dirtydiffDecorator.ts rename to src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/check-inverse.svg b/src/vs/workbench/contrib/scm/browser/media/check-inverse.svg similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/check-inverse.svg rename to src/vs/workbench/contrib/scm/browser/media/check-inverse.svg diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/check.svg b/src/vs/workbench/contrib/scm/browser/media/check.svg similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/check.svg rename to src/vs/workbench/contrib/scm/browser/media/check.svg diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/dirtydiffDecorator.css b/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/dirtydiffDecorator.css rename to src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/icon-dark.svg b/src/vs/workbench/contrib/scm/browser/media/icon-dark.svg similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/icon-dark.svg rename to src/vs/workbench/contrib/scm/browser/media/icon-dark.svg diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/icon-light.svg b/src/vs/workbench/contrib/scm/browser/media/icon-light.svg similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/icon-light.svg rename to src/vs/workbench/contrib/scm/browser/media/icon-light.svg diff --git a/src/vs/workbench/contrib/scm/electron-browser/media/scmViewlet.css b/src/vs/workbench/contrib/scm/browser/media/scmViewlet.css similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/media/scmViewlet.css rename to src/vs/workbench/contrib/scm/browser/media/scmViewlet.css diff --git a/src/vs/workbench/contrib/scm/electron-browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts similarity index 98% rename from src/vs/workbench/contrib/scm/electron-browser/scm.contribution.ts rename to src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 70258e96a6a..9172c0ab736 100644 --- a/src/vs/workbench/contrib/scm/electron-browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -14,7 +14,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { StatusUpdater, StatusBarController } from './scmActivity'; -import { SCMViewlet } from 'vs/workbench/contrib/scm/electron-browser/scmViewlet'; +import { SCMViewlet } from 'vs/workbench/contrib/scm/browser/scmViewlet'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; diff --git a/src/vs/workbench/contrib/scm/electron-browser/scmActivity.ts b/src/vs/workbench/contrib/scm/browser/scmActivity.ts similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/scmActivity.ts rename to src/vs/workbench/contrib/scm/browser/scmActivity.ts diff --git a/src/vs/workbench/contrib/scm/electron-browser/scmMenus.ts b/src/vs/workbench/contrib/scm/browser/scmMenus.ts similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/scmMenus.ts rename to src/vs/workbench/contrib/scm/browser/scmMenus.ts diff --git a/src/vs/workbench/contrib/scm/electron-browser/scmUtil.ts b/src/vs/workbench/contrib/scm/browser/scmUtil.ts similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/scmUtil.ts rename to src/vs/workbench/contrib/scm/browser/scmUtil.ts diff --git a/src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts similarity index 100% rename from src/vs/workbench/contrib/scm/electron-browser/scmViewlet.ts rename to src/vs/workbench/contrib/scm/browser/scmViewlet.ts diff --git a/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts b/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts index 096e70ce7d2..1da752ea1f9 100644 --- a/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts +++ b/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts @@ -6,7 +6,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IColorRegistry, Extensions, ColorContribution } from 'vs/platform/theme/common/colorRegistry'; import { editorMarkerNavigationError } from 'vs/editor/contrib/gotoError/gotoErrorWidget'; -import { overviewRulerModifiedForeground } from 'vs/workbench/contrib/scm/electron-browser/dirtydiffDecorator'; +import { overviewRulerModifiedForeground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; import { STATUS_BAR_DEBUGGING_BACKGROUND } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; import { debugExceptionWidgetBackground } from 'vs/workbench/contrib/debug/browser/exceptionWidget'; import { debugToolBarBackground } from 'vs/workbench/contrib/debug/browser/debugToolbar'; diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 69bf6bcd8ce..3487d9ab09a 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -121,8 +121,8 @@ import 'vs/workbench/contrib/search/browser/searchView'; import 'vs/workbench/contrib/search/browser/openAnythingHandler'; // SCM -import 'vs/workbench/contrib/scm/electron-browser/scm.contribution'; -import 'vs/workbench/contrib/scm/electron-browser/scmViewlet'; +import 'vs/workbench/contrib/scm/browser/scm.contribution'; +import 'vs/workbench/contrib/scm/browser/scmViewlet'; // Debug import 'vs/workbench/contrib/debug/electron-browser/debug.contribution'; From 532213ed2650198c35cc52026efa6f59b055a87f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 11:55:46 +0100 Subject: [PATCH 053/172] :lipstick: --- src/vs/workbench/browser/actions.ts | 11 +-- src/vs/workbench/common/contributions.ts | 13 ++-- src/vs/workbench/common/editor.ts | 11 +-- .../workbench/electron-browser/workbench.ts | 71 +++++++++++-------- .../browser/parts/editor/baseEditor.test.ts | 2 +- .../test/common/editor/editorGroups.test.ts | 10 +-- 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/src/vs/workbench/browser/actions.ts b/src/vs/workbench/browser/actions.ts index c6355e52f00..a31b6947af2 100644 --- a/src/vs/workbench/browser/actions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action, IAction } from 'vs/base/common/actions'; import { BaseActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; -import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; /** * The action bar contributor allows to add actions to an actionbar in a given context. @@ -235,7 +235,10 @@ export interface IActionBarRegistry { */ getActionBarContributors(scope: string): ActionBarContributor[]; - setInstantiationService(service: IInstantiationService): void; + /** + * Starts the registry by providing the required services. + */ + start(accessor: ServicesAccessor): void; } class ActionBarRegistry implements IActionBarRegistry { @@ -243,8 +246,8 @@ class ActionBarRegistry implements IActionBarRegistry { private actionBarContributorInstances: { [scope: string]: ActionBarContributor[] } = Object.create(null); private instantiationService: IInstantiationService; - setInstantiationService(service: IInstantiationService): void { - this.instantiationService = service; + start(accessor: ServicesAccessor): void { + this.instantiationService = accessor.get(IInstantiationService); while (this.actionBarContributorConstructors.length > 0) { const entry = this.actionBarContributorConstructors.shift()!; diff --git a/src/vs/workbench/common/contributions.ts b/src/vs/workbench/common/contributions.ts index 01a8631bf8f..e60c8dbc795 100644 --- a/src/vs/workbench/common/contributions.ts +++ b/src/vs/workbench/common/contributions.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { runWhenIdle, IdleDeadline } from 'vs/base/common/async'; @@ -34,10 +34,9 @@ export interface IWorkbenchContributionsRegistry { /** * Starts the registry by providing the required services. */ - start(instantiationService: IInstantiationService, lifecycleService: ILifecycleService): void; + start(accessor: ServicesAccessor): void; } - class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry { private instantiationService: IInstantiationService; private lifecycleService: ILifecycleService; @@ -63,12 +62,12 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry } } - start(instantiationService: IInstantiationService, lifecycleService: ILifecycleService): void { - this.instantiationService = instantiationService; - this.lifecycleService = lifecycleService; + start(accessor: ServicesAccessor): void { + this.instantiationService = accessor.get(IInstantiationService); + this.lifecycleService = accessor.get(ILifecycleService); [LifecyclePhase.Starting, LifecyclePhase.Ready, LifecyclePhase.Restored, LifecyclePhase.Eventually].forEach(phase => { - this.instantiateByPhase(instantiationService, lifecycleService, phase); + this.instantiateByPhase(this.instantiationService, this.lifecycleService, phase); }); } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index bd9740edb23..6a016bc91cc 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -10,7 +10,7 @@ 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'; import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput } from 'vs/platform/editor/common/editor'; -import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITextModel } from 'vs/editor/common/model'; @@ -175,7 +175,10 @@ export interface IEditorInputFactoryRegistry { */ getEditorInputFactory(editorInputId: string): IEditorInputFactory; - setInstantiationService(service: IInstantiationService): void; + /** + * Starts the registry by providing the required services. + */ + start(accessor: ServicesAccessor): void; } export interface IEditorInputFactory { @@ -1034,8 +1037,8 @@ class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { private editorInputFactoryConstructors: { [editorInputId: string]: IConstructorSignature0 } = Object.create(null); private editorInputFactoryInstances: { [editorInputId: string]: IEditorInputFactory } = Object.create(null); - setInstantiationService(service: IInstantiationService): void { - this.instantiationService = service; + start(accessor: ServicesAccessor): void { + this.instantiationService = accessor.get(IInstantiationService); for (let key in this.editorInputFactoryConstructors) { const element = this.editorInputFactoryConstructors[key]; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index d293d8e11b0..b79377cfcbe 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -311,11 +311,14 @@ export class Workbench extends Disposable implements IPartService { readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), getZoomLevel())); // Create Workbench Container - this.createWorkbench(); + this.createWorkbenchContainer(); // Services this.initServices(this.serviceCollection); + // Registries + this.startRegistries(); + // Context Keys this._register(this.instantiationService.createInstance(WorkbenchContextKeysHandler)); @@ -343,7 +346,7 @@ export class Workbench extends Disposable implements IPartService { return this.restoreParts().then(() => this.whenStarted(), error => this.whenStarted(error)); } - private createWorkbench(): void { + private createWorkbenchContainer(): void { this.workbench = document.createElement('div'); const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac'; @@ -415,8 +418,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService, undefined, true)); // Remote Resolver - const remoteAuthorityResolverService = new RemoteAuthorityResolverService(); - serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService); + serviceCollection.set(IRemoteAuthorityResolverService, new SyncDescriptor(RemoteAuthorityResolverService, undefined, true)); // Remote Agent const remoteAgentService = new RemoteAgentService(this.configuration, this.notificationService, this.environmentService, remoteAuthorityResolverService); @@ -552,15 +554,18 @@ export class Workbench extends Disposable implements IPartService { remoteAgentConnection.registerChannel('loglevel', new LogLevelSetterChannel(this.logService)); } - // Set the some services to registries that have been created eagerly - Registry.as(ActionBarExtensions.Actionbar).setInstantiationService(this.instantiationService); - Registry.as(WorkbenchExtensions.Workbench).start(this.instantiationService, this.lifecycleService); - Registry.as(EditorExtensions.EditorInputFactories).setInstantiationService(this.instantiationService); - // TODO@Sandeep debt around cyclic dependencies this.configurationService.acquireInstantiationService(this.instantiationService); } + private startRegistries(): void { + this.instantiationService.invokeFunction(accessor => { + Registry.as(ActionBarExtensions.Actionbar).start(accessor); + Registry.as(WorkbenchExtensions.Workbench).start(accessor); + Registry.as(EditorExtensions.EditorInputFactories).start(accessor); + }); + } + private hasInitialFilesToOpen(): boolean { return !!( (this.configuration.filesToCreate && this.configuration.filesToCreate.length > 0) || @@ -577,6 +582,25 @@ export class Workbench extends Disposable implements IPartService { this._register(this.configurationService.onDidChangeConfiguration(() => this.setFontAliasing())); } + private fontAliasing: 'default' | 'antialiased' | 'none' | 'auto'; + private setFontAliasing() { + const aliasing = this.configurationService.getValue<'default' | 'antialiased' | 'none' | 'auto'>(Settings.FONT_ALIASING); + if (this.fontAliasing === aliasing) { + return; + } + + this.fontAliasing = aliasing; + + // Remove all + const fontAliasingValues: (typeof aliasing)[] = ['antialiased', 'none', 'auto']; + removeClasses(this.workbench, ...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`)); + + // Add specific + if (fontAliasingValues.some(option => option === aliasing)) { + addClass(this.workbench, `monaco-font-aliasing-${aliasing}`); + } + } + private renderWorkbench(): void { if (this.state.sideBar.hidden) { addClass(this.workbench, 'nosidebar'); @@ -612,25 +636,6 @@ export class Workbench extends Disposable implements IPartService { this.container.appendChild(this.workbench); } - private fontAliasing: 'default' | 'antialiased' | 'none' | 'auto'; - private setFontAliasing() { - const aliasing = this.configurationService.getValue<'default' | 'antialiased' | 'none' | 'auto'>(Settings.FONT_ALIASING); - if (this.fontAliasing === aliasing) { - return; - } - - this.fontAliasing = aliasing; - - // Remove all - const fontAliasingValues: (typeof aliasing)[] = ['antialiased', 'none', 'auto']; - removeClasses(this.workbench, ...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`)); - - // Add specific - if (fontAliasingValues.some(option => option === aliasing)) { - addClass(this.workbench, `monaco-font-aliasing-${aliasing}`); - } - } - private createTitlebarPart(): void { const titlebarContainer = this.createPart(Identifiers.TITLEBAR_PART, 'contentinfo', 'titlebar'); @@ -736,14 +741,20 @@ export class Workbench extends Disposable implements IPartService { if (this.state.sideBar.viewletToRestore) { mark('willRestoreViewlet'); restorePromises.push(this.sidebarPart.openViewlet(this.state.sideBar.viewletToRestore) - .then(viewlet => viewlet || this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId())) + .then(viewlet => { + if (!viewlet) { + return this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId()); // fallback to default viewlet as needed + } + + return viewlet; + }) .then(() => mark('didRestoreViewlet'))); } // Restore Panel if (this.state.panel.panelToRestore) { mark('willRestorePanel'); - this.panelPart.openPanel(this.state.panel.panelToRestore, false); + this.panelPart.openPanel(this.state.panel.panelToRestore); mark('didRestorePanel'); } diff --git a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts index b959ede3928..4f7400dbc91 100644 --- a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts @@ -180,7 +180,7 @@ suite('Workbench base editor', () => { }); test('Editor Input Factory', function () { - EditorInputRegistry.setInstantiationService(workbenchInstantiationService()); + workbenchInstantiationService().invokeFunction(accessor => EditorInputRegistry.start(accessor)); EditorInputRegistry.registerEditorInputFactory('myInputId', MyInputFactory); let factory = EditorInputRegistry.getEditorInputFactory('myInputId'); diff --git a/src/vs/workbench/test/common/editor/editorGroups.test.ts b/src/vs/workbench/test/common/editor/editorGroups.test.ts index bc186f8d331..fde39c097be 100644 --- a/src/vs/workbench/test/common/editor/editorGroups.test.ts +++ b/src/vs/workbench/test/common/editor/editorGroups.test.ts @@ -215,7 +215,7 @@ suite('Workbench editor groups', () => { }); test('group serialization', function () { - Registry.as(EditorExtensions.EditorInputFactories).setInstantiationService(inst()); + inst().invokeFunction(accessor => Registry.as(EditorExtensions.EditorInputFactories).start(accessor)); const group = createGroup(); const input1 = input(); @@ -1003,7 +1003,7 @@ suite('Workbench editor groups', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + inst.invokeFunction(accessor => Registry.as(EditorExtensions.EditorInputFactories).start(accessor)); let group = createGroup(); @@ -1037,7 +1037,7 @@ suite('Workbench editor groups', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + inst.invokeFunction(accessor => Registry.as(EditorExtensions.EditorInputFactories).start(accessor)); let group1 = createGroup(); @@ -1107,7 +1107,7 @@ suite('Workbench editor groups', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + inst.invokeFunction(accessor => Registry.as(EditorExtensions.EditorInputFactories).start(accessor)); let group = createGroup(); @@ -1151,7 +1151,7 @@ suite('Workbench editor groups', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + inst.invokeFunction(accessor => Registry.as(EditorExtensions.EditorInputFactories).start(accessor)); let group1 = createGroup(); let group2 = createGroup(); From 3996321aaa07d3e14fe71aa3b3a3b7f5f1261a26 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 11:59:19 +0100 Subject: [PATCH 054/172] fix compile issue --- src/vs/workbench/electron-browser/workbench.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index b79377cfcbe..9e386737a68 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -421,8 +421,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IRemoteAuthorityResolverService, new SyncDescriptor(RemoteAuthorityResolverService, undefined, true)); // Remote Agent - const remoteAgentService = new RemoteAgentService(this.configuration, this.notificationService, this.environmentService, remoteAuthorityResolverService); - serviceCollection.set(IRemoteAgentService, remoteAgentService); + serviceCollection.set(IRemoteAgentService, new SyncDescriptor(RemoteAgentService, [this.configuration])); // Extensions Management const extensionManagementChannel = getDelayedChannel(sharedProcess.then(c => c.getChannel('extensions'))); @@ -547,12 +546,14 @@ export class Workbench extends Disposable implements IPartService { } // TODO this should move somewhere else - const remoteAgentConnection = remoteAgentService.getConnection(); - if (remoteAgentConnection) { - remoteAgentConnection.registerChannel('dialog', this.instantiationService.createInstance(DialogChannel)); - remoteAgentConnection.registerChannel('download', new DownloadServiceChannel()); - remoteAgentConnection.registerChannel('loglevel', new LogLevelSetterChannel(this.logService)); - } + this.instantiationService.invokeFunction(accessor => { + const remoteAgentConnection = accessor.get(IRemoteAgentService).getConnection(); + if (remoteAgentConnection) { + remoteAgentConnection.registerChannel('dialog', this.instantiationService.createInstance(DialogChannel)); + remoteAgentConnection.registerChannel('download', new DownloadServiceChannel()); + remoteAgentConnection.registerChannel('loglevel', new LogLevelSetterChannel(this.logService)); + } + }); // TODO@Sandeep debt around cyclic dependencies this.configurationService.acquireInstantiationService(this.instantiationService); From 54da2fb645afdb5f4e155f50bf7ec6929f569620 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 12:22:41 +0100 Subject: [PATCH 055/172] :lipstick: --- .../workbench/electron-browser/workbench.ts | 101 +++++++++++------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 9e386737a68..1d3363dfb8b 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -103,6 +103,8 @@ import { WorkbenchThemeService } from 'vs/workbench/services/themes/browser/work import { IProductService } from 'vs/platform/product/common/product'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; // import@node import { BackupFileService, InMemoryBackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; @@ -190,13 +192,17 @@ export class Workbench extends Disposable implements IPartService { private editorService: EditorService; private editorGroupService: IEditorGroupsService; private contextViewService: ContextViewService; - private keybindingService: IKeybindingService; private backupFileService: IBackupFileService; private notificationService: NotificationService; - private themeService: WorkbenchThemeService; - private telemetryService: ITelemetryService; private windowService: IWindowService; private lifecycleService: LifecycleService; + private instantiationService: IInstantiationService; + private contextService: IWorkspaceContextService; + private storageService: IStorageService; + private configurationService: WorkspaceService; + private environmentService: IEnvironmentService; + private logService: ILogService; + private windowsService: IWindowsService; private titlebarPart: TitlebarPart; private activitybarPart: ActivitybarPart; @@ -215,16 +221,24 @@ export class Workbench extends Disposable implements IPartService { private container: HTMLElement, private configuration: IWindowConfiguration, private serviceCollection: ServiceCollection, - @IInstantiationService private readonly instantiationService: IInstantiationService, - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IStorageService private readonly storageService: IStorageService, - @IConfigurationService private readonly configurationService: WorkspaceService, - @IEnvironmentService private readonly environmentService: IEnvironmentService, - @ILogService private readonly logService: ILogService, - @IWindowsService private readonly windowsService: IWindowsService + @IInstantiationService instantiationService: IInstantiationService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IConfigurationService configurationService: WorkspaceService, + @IEnvironmentService environmentService: IEnvironmentService, + @ILogService logService: ILogService, + @IWindowsService windowsService: IWindowsService ) { super(); + this.instantiationService = instantiationService; + this.contextService = contextService; + this.storageService = storageService; + this.configurationService = configurationService; + this.environmentService = environmentService; + this.logService = logService; + this.windowsService = windowsService; + this.registerErrorHandler(); } @@ -343,7 +357,7 @@ export class Workbench extends Disposable implements IPartService { this.lifecycleService.when(LifecyclePhase.Restored).then(() => clearTimeout(timeoutHandle)); // Restore Parts - return this.restoreParts().then(() => this.whenStarted(), error => this.whenStarted(error)); + return this.restoreParts().then(() => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor)), error => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor, error))); } private createWorkbenchContainer(): void { @@ -385,6 +399,7 @@ export class Workbench extends Disposable implements IPartService { }); // Telemetry + let telemetryService: ITelemetryService; if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!productService.enableTelemetry) { const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender'))); const config: ITelemetryServiceConfig = { @@ -393,14 +408,14 @@ export class Workbench extends Disposable implements IPartService { piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath] }; - this.telemetryService = this._register(this.instantiationService.createInstance(TelemetryService, config)); - this._register(new ErrorTelemetry(this.telemetryService)); + telemetryService = this._register(this.instantiationService.createInstance(TelemetryService, config)); + this._register(new ErrorTelemetry(telemetryService)); } else { - this.telemetryService = NullTelemetryService; + telemetryService = NullTelemetryService; } - serviceCollection.set(ITelemetryService, this.telemetryService); - this._register(configurationTelemetry(this.telemetryService, this.configurationService)); + serviceCollection.set(ITelemetryService, telemetryService); + this._register(configurationTelemetry(telemetryService, this.configurationService)); // Lifecycle this.lifecycleService = this.instantiationService.createInstance(LifecycleService); @@ -436,8 +451,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IExtensionService, new SyncDescriptor(ExtensionService)); // Theming - this.themeService = this.instantiationService.createInstance(WorkbenchThemeService, document.body); - serviceCollection.set(IWorkbenchThemeService, this.themeService); + serviceCollection.set(IWorkbenchThemeService, new SyncDescriptor(WorkbenchThemeService, [document.body])); // Commands serviceCollection.set(ICommandService, new SyncDescriptor(CommandService, undefined, true)); @@ -469,8 +483,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IContextKeyService, new SyncDescriptor(ContextKeyService)); // Keybindings - this.keybindingService = this.instantiationService.createInstance(WorkbenchKeybindingService, window); - serviceCollection.set(IKeybindingService, this.keybindingService); + serviceCollection.set(IKeybindingService, new SyncDescriptor(WorkbenchKeybindingService, [window])); // Context view service this.contextViewService = this.instantiationService.createInstance(ContextViewService, this.workbench); @@ -501,10 +514,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IActivityService, new SyncDescriptor(ActivityService, [this.activitybarPart, this.panelPart], true)); // File Service - const fileService = this.instantiationService.createInstance(RemoteFileService); - serviceCollection.set(IFileService, fileService); - this.configurationService.acquireFileService(fileService); - this.themeService.acquireFileService(fileService); + serviceCollection.set(IFileService, new SyncDescriptor(RemoteFileService)); // Editor and Group services this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, !this.hasInitialFilesToOpen()); @@ -545,7 +555,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(contributedService.id, contributedService.descriptor); } - // TODO this should move somewhere else + // TODO@Alex TODO@Sandeep this should move somewhere else this.instantiationService.invokeFunction(accessor => { const remoteAgentConnection = accessor.get(IRemoteAgentService).getConnection(); if (remoteAgentConnection) { @@ -555,8 +565,17 @@ export class Workbench extends Disposable implements IPartService { } }); - // TODO@Sandeep debt around cyclic dependencies - this.configurationService.acquireInstantiationService(this.instantiationService); + // TODO@Sandeep TODO@Martin debt around cyclic dependencies + this.instantiationService.invokeFunction(accessor => { + const fileService = accessor.get(IFileService); + const instantiationService = accessor.get(IInstantiationService); + const themeService = accessor.get(IThemeService) as WorkbenchThemeService; + + this.configurationService.acquireFileService(fileService); + this.configurationService.acquireInstantiationService(instantiationService); + + themeService.acquireFileService(fileService); + }); } private startRegistries(): void { @@ -772,17 +791,25 @@ export class Workbench extends Disposable implements IPartService { return Promise.all(restorePromises); } - private whenStarted(error?: Error): void { + private whenStarted(accessor: ServicesAccessor, error?: Error): void { + const themeService = accessor.get(IWorkbenchThemeService); + const keybindingsService = accessor.get(IKeybindingService); + const lifecycleService = accessor.get(ILifecycleService) as LifecycleService; + const editorService = accessor.get(IEditorService); + const activityService = accessor.get(IActivityService); + const contextService = accessor.get(IWorkspaceContextService); + const telemetryService = accessor.get(ITelemetryService); + this.restored = true; // Set lifecycle phase to `Restored` - this.lifecycleService.phase = LifecyclePhase.Restored; + lifecycleService.phase = LifecyclePhase.Restored; // Set lifecycle phase to `Eventually` after a short delay and when // idle (min 2.5sec, max 5sec) setTimeout(() => { this._register(runWhenIdle(() => { - this.lifecycleService.phase = LifecyclePhase.Eventually; + lifecycleService.phase = LifecyclePhase.Eventually; }, 2500)); }, 2500); @@ -813,20 +840,20 @@ export class Workbench extends Disposable implements IPartService { "startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ - this.telemetryService.publicLog('workspaceLoad', { + telemetryService.publicLog('workspaceLoad', { userAgent: navigator.userAgent, windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, - emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY, + emptyWorkbench: contextService.getWorkbenchState() === WorkbenchState.EMPTY, 'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0, 'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0, 'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0, - customKeybindingsCount: this.keybindingService.customKeybindingsCount(), - theme: this.themeService.getColorTheme().id, + customKeybindingsCount: keybindingsService.customKeybindingsCount(), + theme: themeService.getColorTheme().id, language, - pinnedViewlets: this.activitybarPart.getPinnedViewletIds(), + pinnedViewlets: activityService.getPinnedViewletIds(), restoredViewlet: this.state.sideBar.viewletToRestore, - restoredEditors: this.editorService.visibleEditors.length, - startupKind: this.lifecycleService.startupKind + restoredEditors: editorService.visibleEditors.length, + startupKind: lifecycleService.startupKind }); // Telemetry: startup metrics From ef20041efe558573f442e0eccdc7b41af2430d75 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 12:24:55 +0100 Subject: [PATCH 056/172] use IWorkbenchThemeService as import --- src/vs/workbench/electron-browser/workbench.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 1d3363dfb8b..44ec80fb496 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -104,7 +104,6 @@ import { IProductService } from 'vs/platform/product/common/product'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; // import@node import { BackupFileService, InMemoryBackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; @@ -569,7 +568,7 @@ export class Workbench extends Disposable implements IPartService { this.instantiationService.invokeFunction(accessor => { const fileService = accessor.get(IFileService); const instantiationService = accessor.get(IInstantiationService); - const themeService = accessor.get(IThemeService) as WorkbenchThemeService; + const themeService = accessor.get(IWorkbenchThemeService) as WorkbenchThemeService; this.configurationService.acquireFileService(fileService); this.configurationService.acquireInstantiationService(instantiationService); From e8e7703ab497f70677e922434393ff5be100b109 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 12:30:06 +0100 Subject: [PATCH 057/172] fix #69406 --- .../services/markerDecorationsServiceImpl.ts | 27 ++++++++++++++++--- .../services/markersDecorationService.ts | 8 +++++- .../contrib/documentSymbols/outlineModel.ts | 20 +++++++++----- .../contrib/outline/browser/outlinePanel.ts | 22 +++++++-------- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/common/services/markerDecorationsServiceImpl.ts b/src/vs/editor/common/services/markerDecorationsServiceImpl.ts index ecf4af882d6..70748519a41 100644 --- a/src/vs/editor/common/services/markerDecorationsServiceImpl.ts +++ b/src/vs/editor/common/services/markerDecorationsServiceImpl.ts @@ -15,6 +15,7 @@ import { Range } from 'vs/editor/common/core/range'; import { keys } from 'vs/base/common/map'; import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService'; import { Schemas } from 'vs/base/common/network'; +import { Emitter, Event } from 'vs/base/common/event'; function MODEL_ID(resource: URI): string { return resource.toString(); @@ -44,12 +45,26 @@ class MarkerDecorations extends Disposable { getMarker(decoration: IModelDecoration): IMarker | undefined { return this._markersData.get(decoration.id); } + + getMarkers(): [Range, IMarker][] { + const res: [Range, IMarker][] = []; + this._markersData.forEach((marker, id) => { + let range = this.model.getDecorationRange(id); + if (range) { + res.push([range, marker]); + } + }); + return res; + } } export class MarkerDecorationsService extends Disposable implements IMarkerDecorationsService { _serviceBrand: any; + private readonly _onDidChangeMarker = new Emitter(); + readonly onDidChangeMarker: Event = this._onDidChangeMarker.event; + private readonly _markerDecorations: Map = new Map(); constructor( @@ -68,11 +83,16 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor return markerDecorations ? markerDecorations.getMarker(decoration) || null : null; } + getLiveMarkers(model: ITextModel): [Range, IMarker][] { + const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri)); + return markerDecorations ? markerDecorations.getMarkers() : []; + } + private _handleMarkerChange(changedResources: URI[]): void { changedResources.forEach((resource) => { const markerDecorations = this._markerDecorations.get(MODEL_ID(resource)); if (markerDecorations) { - this.updateDecorations(markerDecorations); + this._updateDecorations(markerDecorations); } }); } @@ -80,7 +100,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor private _onModelAdded(model: ITextModel): void { const markerDecorations = new MarkerDecorations(model); this._markerDecorations.set(MODEL_ID(model.uri), markerDecorations); - this.updateDecorations(markerDecorations); + this._updateDecorations(markerDecorations); } private _onModelRemoved(model: ITextModel): void { @@ -100,7 +120,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor } } - private updateDecorations(markerDecorations: MarkerDecorations): void { + private _updateDecorations(markerDecorations: MarkerDecorations): void { // Limit to the first 500 errors/warnings const markers = this._markerService.read({ resource: markerDecorations.model.uri, take: 500 }); let newModelDecorations: IModelDeltaDecoration[] = markers.map((marker) => { @@ -110,6 +130,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor }; }); markerDecorations.update(markers, newModelDecorations); + this._onDidChangeMarker.fire(markerDecorations.model); } private _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range { diff --git a/src/vs/editor/common/services/markersDecorationService.ts b/src/vs/editor/common/services/markersDecorationService.ts index b2424a4d312..44aa7ca2463 100644 --- a/src/vs/editor/common/services/markersDecorationService.ts +++ b/src/vs/editor/common/services/markersDecorationService.ts @@ -6,11 +6,17 @@ import { ITextModel, IModelDecoration } from 'vs/editor/common/model'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IMarker } from 'vs/platform/markers/common/markers'; +import { Event } from 'vs/base/common/event'; +import { Range } from 'vs/editor/common/core/range'; export const IMarkerDecorationsService = createDecorator('markerDecorationsService'); export interface IMarkerDecorationsService { _serviceBrand: any; + onDidChangeMarker: Event; + getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null; -} \ No newline at end of file + + getLiveMarkers(model: ITextModel): [Range, IMarker][]; +} diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts index 759ea82e044..61991f8a654 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts @@ -13,7 +13,7 @@ import { IPosition } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; import { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; -import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers'; +import { MarkerSeverity } from 'vs/platform/markers/common/markers'; export abstract class TreeElement { @@ -86,6 +86,14 @@ export abstract class TreeElement { } } +export interface IOutlineMarker { + startLineNumber: number; + startColumn: number; + endLineNumber: number; + endColumn: number; + severity: MarkerSeverity; +} + export class OutlineElement extends TreeElement { children: { [id: string]: OutlineElement; } = Object.create(null); @@ -140,13 +148,13 @@ export class OutlineGroup extends TreeElement { return undefined; } - updateMarker(marker: IMarker[]): void { + updateMarker(marker: IOutlineMarker[]): void { for (const key in this.children) { this._updateMarker(marker, this.children[key]); } } - private _updateMarker(markers: IMarker[], item: OutlineElement): void { + private _updateMarker(markers: IOutlineMarker[], item: OutlineElement): void { item.marker = undefined; // find the proper start index to check for item/marker overlap. @@ -161,7 +169,7 @@ export class OutlineGroup extends TreeElement { start = idx; } - let myMarkers: IMarker[] = []; + let myMarkers: IOutlineMarker[] = []; let myTopSev: MarkerSeverity | undefined; for (; start < markers.length && Range.areIntersecting(item.symbol.range, markers[start]); start++) { @@ -169,7 +177,7 @@ export class OutlineGroup extends TreeElement { // and store them in a 'private' array. let marker = markers[start]; myMarkers.push(marker); - (markers as Array)[start] = undefined; + (markers as Array)[start] = undefined; if (!myTopSev || marker.severity > myTopSev) { myTopSev = marker.severity; } @@ -413,7 +421,7 @@ export class OutlineModel extends TreeElement { return TreeElement.getElementById(id, this); } - updateMarker(marker: IMarker[]): void { + updateMarker(marker: IOutlineMarker[]): void { // sort markers by start range so that we can use // outline element starts for quicker look up marker.sort(Range.compareRangesUsingStarts); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index 59dbfe4c344..a083b522f01 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -7,7 +7,6 @@ import * as dom from 'vs/base/browser/dom'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { Action, IAction, RadioGroup } from 'vs/base/common/actions'; -import { firstIndex } from 'vs/base/common/arrays'; import { createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Emitter } from 'vs/base/common/event'; @@ -15,7 +14,6 @@ import { defaultGenerator } from 'vs/base/common/idGenerator'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { LRUCache } from 'vs/base/common/map'; import { escape } from 'vs/base/common/strings'; -import { URI } from 'vs/base/common/uri'; import 'vs/css!./outlinePanel'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; @@ -24,7 +22,7 @@ import { ITextModel } from 'vs/editor/common/model'; import { IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureRegistry'; -import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; +import { OutlineElement, OutlineModel, TreeElement, IOutlineMarker } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -33,7 +31,6 @@ import { IResourceInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { WorkbenchDataTree } from 'vs/platform/list/browser/listService'; -import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -48,6 +45,7 @@ import { IDataTreeViewState } from 'vs/base/browser/ui/tree/dataTree'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { basename } from 'vs/base/common/resources'; import { IDataSource } from 'vs/base/browser/ui/tree/tree'; +import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService'; class RequestState { @@ -261,7 +259,7 @@ export class OutlinePanel extends ViewletPanel { @IThemeService private readonly _themeService: IThemeService, @IStorageService private readonly _storageService: IStorageService, @IEditorService private readonly _editorService: IEditorService, - @IMarkerService private readonly _markerService: IMarkerService, + @IMarkerDecorationsService private readonly _markerDecorationService: IMarkerDecorationsService, @IConfigurationService private readonly _configurationService: IConfigurationService, @IKeybindingService keybindingService: IKeybindingService, @IConfigurationService configurationService: IConfigurationService, @@ -569,21 +567,23 @@ export class OutlinePanel extends ViewletPanel { })); // feature: show markers in outline - const updateMarker = (e: URI[], ignoreEmpty?: boolean) => { + const updateMarker = (model: ITextModel, ignoreEmpty?: boolean) => { if (!this._configurationService.getValue(OutlineConfigKeys.problemsEnabled)) { return; } - if (firstIndex(e, a => a.toString() === textModel.uri.toString()) < 0) { + if (model !== textModel) { return; } - const marker = this._markerService.read({ resource: textModel.uri, severities: MarkerSeverity.Error | MarkerSeverity.Warning }); + const marker = this._markerDecorationService.getLiveMarkers(textModel).map(([range, marker]) => { + return { ...range, severity: marker.severity } as IOutlineMarker; + }); if (marker.length > 0 || !ignoreEmpty) { newModel.updateMarker(marker); this._tree.updateChildren(); } }; - updateMarker([textModel.uri], true); - this._editorDisposables.push(this._markerService.onMarkerChanged(updateMarker)); + updateMarker(textModel, true); + this._editorDisposables.push(this._markerDecorationService.onDidChangeMarker(updateMarker)); this._editorDisposables.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(OutlineConfigKeys.problemsBadges) || e.affectsConfiguration(OutlineConfigKeys.problemsColors)) { @@ -597,7 +597,7 @@ export class OutlinePanel extends ViewletPanel { newModel.updateMarker([]); this._tree.updateChildren(); } else { - updateMarker([textModel.uri], true); + updateMarker(textModel, true); } })); } From f9bda10403d717dba8da40d8c04db8e95ce4fe35 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 12:43:22 +0100 Subject: [PATCH 058/172] debt - extract a telemetry workbench contribution --- .../browser/telemetry.contribution.ts | 90 +++++++++++++++++++ .../workbench/electron-browser/workbench.ts | 57 ++---------- src/vs/workbench/workbench.main.ts | 3 + 3 files changed, 99 insertions(+), 51 deletions(-) create mode 100644 src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts diff --git a/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts new file mode 100644 index 00000000000..b2ca963f342 --- /dev/null +++ b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts @@ -0,0 +1,90 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IActivityService } from 'vs/workbench/services/activity/common/activity'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { language } from 'vs/base/common/platform'; +import { Disposable } from 'vs/base/common/lifecycle'; +import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; +import { configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; + +export class TelemetryContribution extends Disposable implements IWorkbenchContribution { + + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IActivityService activityService: IActivityService, + @ILifecycleService lifecycleService: ILifecycleService, + @IEditorService editorService: IEditorService, + @IKeybindingService keybindingsService: IKeybindingService, + @IWorkbenchThemeService themeService: IWorkbenchThemeService, + @IWindowService windowService: IWindowService, + @IConfigurationService configurationService: IConfigurationService, + @IViewletService viewletService: IViewletService + ) { + super(); + + const { filesToOpen, filesToCreate, filesToDiff } = windowService.getConfiguration(); + const activeViewlet = viewletService.getActiveViewlet(); + + /* __GDPR__ + "workspaceLoad" : { + "userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" }, + "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + telemetryService.publicLog('workspaceLoad', { + userAgent: navigator.userAgent, + windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, + emptyWorkbench: contextService.getWorkbenchState() === WorkbenchState.EMPTY, + 'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0, + 'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0, + 'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0, + customKeybindingsCount: keybindingsService.customKeybindingsCount(), + theme: themeService.getColorTheme().id, + language, + pinnedViewlets: activityService.getPinnedViewletIds(), + restoredViewlet: activeViewlet ? activeViewlet.getId() : undefined, + restoredEditors: editorService.visibleEditors.length, + startupKind: lifecycleService.startupKind + }); + + // Error Telemetry + this._register(new ErrorTelemetry(telemetryService)); + + // Configuration Telemetry + this._register(configurationTelemetry(telemetryService, configurationService)); + + // Lifecycle + this._register(lifecycleService.onShutdown(() => this.dispose())); + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TelemetryContribution, LifecyclePhase.Restored); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 44ec80fb496..61dc43e4a62 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -16,7 +16,7 @@ import { mark } from 'vs/base/common/performance'; import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { Registry } from 'vs/platform/registry/common/platform'; -import { isWindows, isLinux, isMacintosh, language } from 'vs/base/common/platform'; +import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; import { IResourceInput } from 'vs/platform/editor/common/editor'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, IUntitledResourceInput, IResourceDiffInput } from 'vs/workbench/common/editor'; @@ -82,8 +82,7 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { ILabelService } from 'vs/platform/label/common/label'; import { LabelService } from 'vs/workbench/services/label/common/labelService'; import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; -import { combinedAppender, LogAppender, NullTelemetryService, configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils'; -import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; +import { combinedAppender, LogAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { IExtensionGalleryService, IExtensionManagementServerService, IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; @@ -356,7 +355,10 @@ export class Workbench extends Disposable implements IPartService { this.lifecycleService.when(LifecyclePhase.Restored).then(() => clearTimeout(timeoutHandle)); // Restore Parts - return this.restoreParts().then(() => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor)), error => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor, error))); + let error: Error; + return this.restoreParts() + .catch(err => error = err) + .finally(() => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor, error))); } private createWorkbenchContainer(): void { @@ -408,13 +410,11 @@ export class Workbench extends Disposable implements IPartService { }; telemetryService = this._register(this.instantiationService.createInstance(TelemetryService, config)); - this._register(new ErrorTelemetry(telemetryService)); } else { telemetryService = NullTelemetryService; } serviceCollection.set(ITelemetryService, telemetryService); - this._register(configurationTelemetry(telemetryService, this.configurationService)); // Lifecycle this.lifecycleService = this.instantiationService.createInstance(LifecycleService); @@ -791,13 +791,7 @@ export class Workbench extends Disposable implements IPartService { } private whenStarted(accessor: ServicesAccessor, error?: Error): void { - const themeService = accessor.get(IWorkbenchThemeService); - const keybindingsService = accessor.get(IKeybindingService); const lifecycleService = accessor.get(ILifecycleService) as LifecycleService; - const editorService = accessor.get(IEditorService); - const activityService = accessor.get(IActivityService); - const contextService = accessor.get(IWorkspaceContextService); - const telemetryService = accessor.get(ITelemetryService); this.restored = true; @@ -816,45 +810,6 @@ export class Workbench extends Disposable implements IPartService { onUnexpectedError(error); } - const { filesToOpen, filesToCreate, filesToDiff } = this.configuration; - - /* __GDPR__ - "workspaceLoad" : { - "userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" }, - "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } - } - */ - telemetryService.publicLog('workspaceLoad', { - userAgent: navigator.userAgent, - windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, - emptyWorkbench: contextService.getWorkbenchState() === WorkbenchState.EMPTY, - 'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0, - 'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0, - 'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0, - customKeybindingsCount: keybindingsService.customKeybindingsCount(), - theme: themeService.getColorTheme().id, - language, - pinnedViewlets: activityService.getPinnedViewletIds(), - restoredViewlet: this.state.sideBar.viewletToRestore, - restoredEditors: editorService.visibleEditors.length, - startupKind: lifecycleService.startupKind - }); - // Telemetry: startup metrics mark('didStartWorkbench'); } diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 3487d9ab09a..ceffd2a8727 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -88,6 +88,9 @@ registerSingleton(IClipboardService, ClipboardService, true); //#region --- workbench contributions +// Telemetry +import 'vs/workbench/contrib/telemetry/browser/telemetry.contribution'; + // Localizations import 'vs/workbench/contrib/localizations/browser/localizations.contribution'; From 3c209bdc83fc18fa0022015a49bc6c693dc79185 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 5 Mar 2019 12:53:36 +0100 Subject: [PATCH 059/172] fix #65997 --- src/vs/editor/common/services/editorSimpleWorker.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 4ef83f744a7..f5564b6f567 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -491,12 +491,15 @@ export abstract class BaseEditorSimpleWorker { return Promise.resolve(null); } + const seen: Record = Object.create(null); const suggestions: CompletionItem[] = []; const wordDefRegExp = new RegExp(wordDef, wordDefFlags); - const currentWord = model.getWordUntilPosition(position, wordDefRegExp); + const wordUntil = model.getWordUntilPosition(position, wordDefRegExp); - const seen: Record = Object.create(null); - seen[currentWord.word] = true; + const wordAt = model.getWordAtPosition(position, wordDefRegExp); + if (wordAt) { + seen[model.getValueInRange(wordAt)] = true; + } for ( let iter = model.createWordIterator(wordDefRegExp), e = iter.next(); @@ -516,10 +519,9 @@ export abstract class BaseEditorSimpleWorker { kind: CompletionItemKind.Text, label: word, insertText: word, - range: { startLineNumber: position.lineNumber, startColumn: currentWord.startColumn, endLineNumber: position.lineNumber, endColumn: currentWord.endColumn } + range: { startLineNumber: position.lineNumber, startColumn: wordUntil.startColumn, endLineNumber: position.lineNumber, endColumn: wordUntil.endColumn } }); } - return Promise.resolve({ suggestions }); } From f7f4357b9f4dc26483bf621e4dc9269469146491 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 12:56:38 +0100 Subject: [PATCH 060/172] services - sync descriptor for notification service --- src/vs/editor/common/controller/cursor.ts | 4 ++-- .../workbench/electron-browser/workbench.ts | 22 +++++++------------ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 15ccc7a4e1f..81493777b1c 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import * as strings from 'vs/base/common/strings'; @@ -828,7 +827,8 @@ class CommandExecutor { try { command.getEditOperations(ctx.model, editOperationBuilder); } catch (e) { - e.friendlyMessage = nls.localize('corrupt.commands', "Unexpected exception while executing command."); + // TODO@Alex use notification service if this should be user facing + // e.friendlyMessage = nls.localize('corrupt.commands', "Unexpected exception while executing command."); onUnexpectedError(e); return { operations: [], diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 61dc43e4a62..b1e469d99db 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -191,7 +191,6 @@ export class Workbench extends Disposable implements IPartService { private editorGroupService: IEditorGroupsService; private contextViewService: ContextViewService; private backupFileService: IBackupFileService; - private notificationService: NotificationService; private windowService: IWindowService; private lifecycleService: LifecycleService; private instantiationService: IInstantiationService; @@ -281,11 +280,6 @@ export class Workbench extends Disposable implements IPartService { // Log it this.logService.error(errorMsg); - - // Show to user if friendly message provided - if (error && error.friendlyMessage && this.notificationService) { - this.notificationService.error(error.friendlyMessage); - } } startup(): void { @@ -379,8 +373,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true)); // Notifications - this.notificationService = new NotificationService(); - serviceCollection.set(INotificationService, this.notificationService); + serviceCollection.set(INotificationService, new SyncDescriptor(NotificationService, undefined, true)); // Window this.windowService = this.instantiationService.createInstance(WindowService, this.configuration); @@ -649,7 +642,7 @@ export class Workbench extends Disposable implements IPartService { this.createStatusbarPart(); // Notification Handlers - this.createNotificationsHandlers(); + this.instantiationService.invokeFunction(accessor => this.createNotificationsHandlers(accessor)); // Add Workbench to DOM this.container.appendChild(this.workbench); @@ -706,19 +699,20 @@ export class Workbench extends Disposable implements IPartService { return part; } - private createNotificationsHandlers(): void { + private createNotificationsHandlers(accessor: ServicesAccessor): void { + const notificationService = accessor.get(INotificationService) as NotificationService; // Notifications Center - this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, this.notificationService.model)); + this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, notificationService.model)); // Notifications Toasts - this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, this.notificationService.model)); + this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, notificationService.model)); // Notifications Alerts - this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model)); + this._register(this.instantiationService.createInstance(NotificationsAlerts, notificationService.model)); // Notifications Status - const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, this.notificationService.model); + const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, notificationService.model); // Eventing this._register(this.notificationsCenter.onDidChangeVisibility(() => { From c9370aeaf10450c09b6bb1f25fcc9d70ed5b48e9 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 5 Mar 2019 15:21:23 +0100 Subject: [PATCH 061/172] [css] updates service (multi-semantic selection, webpack) --- .../client/src/cssMain.ts | 42 +++++-------------- extensions/css-language-features/package.json | 2 +- .../server/build/filesFillIn.js | 5 --- .../server/extension.webpack.config.js | 10 +---- .../css-language-features/server/package.json | 4 +- .../server/src/cssServerMain.ts | 6 +-- .../css-language-features/server/yarn.lock | 38 ++++++++--------- extensions/css-language-features/yarn.lock | 28 ++++++------- 8 files changed, 51 insertions(+), 84 deletions(-) delete mode 100644 extensions/css-language-features/server/build/filesFillIn.js diff --git a/extensions/css-language-features/client/src/cssMain.ts b/extensions/css-language-features/client/src/cssMain.ts index 0312498f672..641d11f335b 100644 --- a/extensions/css-language-features/client/src/cssMain.ts +++ b/extensions/css-language-features/client/src/cssMain.ts @@ -9,8 +9,8 @@ import * as fs from 'fs'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString, workspace, TextDocument, SelectionRange, SelectionRangeKind } from 'vscode'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Disposable, TextDocumentIdentifier } from 'vscode-languageclient'; +import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString, workspace, TextDocument, SelectionRange } from 'vscode'; +import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Disposable } from 'vscode-languageclient'; import { getCustomDataPathsInAllWorkspaces, getCustomDataPathsFromAllExtensions } from './customData'; // this method is called when vs code is activated @@ -83,43 +83,23 @@ export function activate(context: ExtensionContext) { context.subscriptions.push(languages.registerSelectionRangeProvider(selector, { async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise { const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(document); - return Promise.all(positions.map(async position => { - const rawRanges = await client.sendRequest('$/textDocument/selectionRange', { textDocument, position }); - if (Array.isArray(rawRanges)) { - return rawRanges.map(r => { + const rawResult = await client.sendRequest('$/textDocument/selectionRanges', { textDocument, positions: positions.map(client.code2ProtocolConverter.asPosition) }); + if (Array.isArray(rawResult)) { + return rawResult.map(rawSelectionRanges => { + return rawSelectionRanges.map(selectionRange => { return { - range: client.protocol2CodeConverter.asRange(r), - kind: SelectionRangeKind.Declaration + range: client.protocol2CodeConverter.asRange(selectionRange.range), + kind: selectionRange.kind }; }); - } - return []; - })); + }); + } + return []; } })); }); }); - const selectionRangeProvider = { - async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise { - const textDocument = TextDocumentIdentifier.create(document.uri.toString()); - return Promise.all(positions.map(async position => { - const rawRanges: Range[] = await client.sendRequest('$/textDocument/selectionRange', { textDocument, position }); - - return rawRanges.map(r => { - const actualRange = new Range(new Position(r.start.line, r.start.character), new Position(r.end.line, r.end.character)); - return { - range: actualRange, - kind: SelectionRangeKind.Declaration - }; - }); - })); - } - }; - documentSelector.forEach(selector => { - languages.registerSelectionRangeProvider(selector, selectionRangeProvider); - }); - function initCompletionProvider(): Disposable { const regionCompletionRegExpr = /^(\s*)(\/(\*\s*(#\w*)?)?)?$/; diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 99b022469d6..ac8a4b23c72 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -726,7 +726,7 @@ ] }, "dependencies": { - "vscode-languageclient": "^5.1.0", + "vscode-languageclient": "^5.2.1", "vscode-nls": "^4.0.0" }, "devDependencies": { diff --git a/extensions/css-language-features/server/build/filesFillIn.js b/extensions/css-language-features/server/build/filesFillIn.js deleted file mode 100644 index 906617384e0..00000000000 --- a/extensions/css-language-features/server/build/filesFillIn.js +++ /dev/null @@ -1,5 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -module.exports = {}; \ No newline at end of file diff --git a/extensions/css-language-features/server/extension.webpack.config.js b/extensions/css-language-features/server/extension.webpack.config.js index 17dc2d39e34..68b850b3773 100644 --- a/extensions/css-language-features/server/extension.webpack.config.js +++ b/extensions/css-language-features/server/extension.webpack.config.js @@ -9,7 +9,6 @@ const withDefaults = require('../../shared.webpack.config'); const path = require('path'); -var webpack = require('webpack'); module.exports = withDefaults({ context: path.join(__dirname), @@ -19,12 +18,5 @@ module.exports = withDefaults({ output: { filename: 'cssServerMain.js', path: path.join(__dirname, 'dist') - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), - new webpack.IgnorePlugin(/vertx/) - ], + } }); diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 9bc32c0a788..71e14f56ea2 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,8 +9,8 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^3.0.13-next.12", - "vscode-languageserver": "^5.1.0" + "vscode-css-languageservice": "^4.0.0-next.3", + "vscode-languageserver": "^5.3.0-next.2" }, "devDependencies": { "@types/mocha": "2.2.33", diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index 3ef166f1b80..e1c78b158c1 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -335,14 +335,14 @@ connection.onFoldingRanges((params, token) => { }, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token); }); -connection.onRequest('$/textDocument/selectionRange', async (params, token) => { +connection.onRequest('$/textDocument/selectionRanges', async (params, token) => { return runSafe(() => { const document = documents.get(params.textDocument.uri); - const position: Position = params.position; + const positions: Position[] = params.positions; if (document) { const stylesheet = stylesheets.get(document); - return getLanguageService(document).getSelectionRanges(document, position, stylesheet); + return getLanguageService(document).getSelectionRanges(document, positions, stylesheet); } return Promise.resolve(null); }, null, `Error while computing selection ranges for ${params.textDocument.uri}`, token); diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index a2fa388731d..bfbcab4c931 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -229,12 +229,12 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^3.0.13-next.12: - version "3.0.13-next.12" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-3.0.13-next.12.tgz#8d20828e41bc7dcf44cdba4b2e476393780a7793" - integrity sha512-5B3NYU2DBFhbUvMuTg7kBlc9COHyr/pbR1cDzXGFwemQG8W6ERsgn+eftPHFbcug1kwBjPVSoMgtw/czKpboHQ== +vscode-css-languageservice@^4.0.0-next.3: + version "4.0.0-next.3" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.0-next.3.tgz#e9529f3b4ddf95c9a3e5dc2a6d701a38280ffa98" + integrity sha512-/xmbWpIQLw+HZ/3LsaE2drHFSNJbM9mZ8bKR5NUiu2ZUr10WbGxX0j/GDZB3LlMmdSHQGgRQ5hTM/Ic2PuBDRw== dependencies: - vscode-languageserver-types "^3.13.0" + vscode-languageserver-types "^3.14.0" vscode-nls "^4.0.0" vscode-jsonrpc@^4.0.0: @@ -242,25 +242,25 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.15.0-next.1: + version "3.15.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.1.tgz#1e45e224d7eef8c79b4bed75b9dcb1930d2ab8ed" + integrity sha512-LXF0d9s3vxFBxVQ4aKl/XghdEMAncGt3dh4urIYa9Is43g3MfIQL9fC44YZtP+XXOrI2rpZU8lRNN01U1V6CDg== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0, vscode-languageserver-types@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0, vscode-languageserver-types@^3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== -vscode-languageserver@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz#012a28f154cc7a848c443d217894942e4c3eeb39" - integrity sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw== +vscode-languageserver@^5.3.0-next.2: + version "5.3.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.2.tgz#31ce4c34d68b517b400ca9e211e43f8d868b8dcc" + integrity sha512-n5onRw9naMrRHp2jnOn+ZwN1n+tTfzftWLPonjp1FWf/iCZWIlnw2TyF/Hn+SDGhLoVtoghmxhwEQaxEAfLHvw== dependencies: - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.15.0-next.1" vscode-uri "^1.0.6" vscode-nls@^4.0.0: diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 6314214090a..385d59738dd 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -167,26 +167,26 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageclient@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz#650ab0dc9fd0daaade058a8471aaff5bc3f9580e" - integrity sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg== +vscode-languageclient@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz#7cfc83a294c409f58cfa2b910a8cfeaad0397193" + integrity sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q== dependencies: semver "^5.5.0" - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.14.1" -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f" + integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== vscode-nls@^4.0.0: version "4.0.0" From 8e986b18a0bc1656cbde8c13ecb5f9b78c1bc803 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 5 Mar 2019 15:22:49 +0100 Subject: [PATCH 062/172] [html] update service (multi semantic selection, webpack) --- .../client/src/htmlMain.ts | 20 ++++---- .../html-language-features/package.json | 2 +- .../server/build/filesFillIn.js | 5 -- .../server/extension.webpack.config.js | 10 +--- .../server/package.json | 8 ++-- .../server/src/customData.ts | 4 +- .../server/src/htmlServerMain.ts | 8 ++-- .../server/src/modes/htmlMode.ts | 6 +-- .../server/src/modes/languageModes.ts | 4 +- .../html-language-features/server/yarn.lock | 48 +++++++++---------- extensions/html-language-features/yarn.lock | 28 +++++------ 11 files changed, 65 insertions(+), 78 deletions(-) delete mode 100644 extensions/html-language-features/server/build/filesFillIn.js diff --git a/extensions/html-language-features/client/src/htmlMain.ts b/extensions/html-language-features/client/src/htmlMain.ts index 696bc074c84..27f3ad2d626 100644 --- a/extensions/html-language-features/client/src/htmlMain.ts +++ b/extensions/html-language-features/client/src/htmlMain.ts @@ -8,7 +8,7 @@ import * as fs from 'fs'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, SelectionRange, SelectionRangeKind } from 'vscode'; +import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, SelectionRange } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams } from 'vscode-languageclient'; import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared'; import { activateTagClosing } from './tagClosing'; @@ -92,18 +92,18 @@ export function activate(context: ExtensionContext) { context.subscriptions.push(languages.registerSelectionRangeProvider(selector, { async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise { const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(document); - return Promise.all(positions.map(async position => { - const rawRanges = await client.sendRequest('$/textDocument/selectionRange', { textDocument, position }); - if (Array.isArray(rawRanges)) { - return rawRanges.map(r => { + const rawResult = await client.sendRequest('$/textDocument/selectionRanges', { textDocument, positions: positions.map(client.code2ProtocolConverter.asPosition) }); + if (Array.isArray(rawResult)) { + return rawResult.map(rawSelectionRanges => { + return rawSelectionRanges.map(selectionRange => { return { - range: client.protocol2CodeConverter.asRange(r), - kind: SelectionRangeKind.Declaration + range: client.protocol2CodeConverter.asRange(selectionRange.range), + kind: selectionRange.kind }; }); - } - return []; - })); + }); + } + return []; } })); }); diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 64fe111d64b..e44dc9f7102 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -176,7 +176,7 @@ }, "dependencies": { "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "^5.1.0", + "vscode-languageclient": "^5.2.1", "vscode-nls": "^4.0.0" }, "devDependencies": { diff --git a/extensions/html-language-features/server/build/filesFillIn.js b/extensions/html-language-features/server/build/filesFillIn.js deleted file mode 100644 index 906617384e0..00000000000 --- a/extensions/html-language-features/server/build/filesFillIn.js +++ /dev/null @@ -1,5 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -module.exports = {}; \ No newline at end of file diff --git a/extensions/html-language-features/server/extension.webpack.config.js b/extensions/html-language-features/server/extension.webpack.config.js index a535ddeae9a..77b86e718b1 100644 --- a/extensions/html-language-features/server/extension.webpack.config.js +++ b/extensions/html-language-features/server/extension.webpack.config.js @@ -9,7 +9,6 @@ const withDefaults = require('../../shared.webpack.config'); const path = require('path'); -var webpack = require('webpack'); module.exports = withDefaults({ context: path.join(__dirname), @@ -22,12 +21,5 @@ module.exports = withDefaults({ }, externals: { 'typescript': 'commonjs typescript' - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), - new webpack.IgnorePlugin(/vertx/) - ], + } }); diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index bfc23ebe0bc..b01c03a3f15 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,10 +9,10 @@ }, "main": "./out/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^3.0.13-next.10", - "vscode-html-languageservice": "^2.1.11", - "vscode-languageserver": "^5.1.0", - "vscode-languageserver-types": "^3.13.0", + "vscode-css-languageservice": "^4.0.0-next.3", + "vscode-html-languageservice": "^3.0.0-next.3", + "vscode-languageserver": "^5.3.0-next.2", + "vscode-languageserver-types": "^3.14.0", "vscode-nls": "^4.0.0", "vscode-uri": "^1.0.6" }, diff --git a/extensions/html-language-features/server/src/customData.ts b/extensions/html-language-features/server/src/customData.ts index 673e4a4ab9d..1d550eddf9f 100644 --- a/extensions/html-language-features/server/src/customData.ts +++ b/extensions/html-language-features/server/src/customData.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IHTMLDataProvider, HTMLDataProvider } from 'vscode-html-languageservice'; +import { IHTMLDataProvider, newHTMLDataProvider } from 'vscode-html-languageservice'; import * as fs from 'fs'; export function getDataProviders(dataPaths?: string[]): IHTMLDataProvider[] { @@ -18,7 +18,7 @@ export function getDataProviders(dataPaths?: string[]): IHTMLDataProvider[] { if (fs.existsSync(path)) { const htmlData = JSON.parse(fs.readFileSync(path, 'utf-8')); - providers.push(new HTMLDataProvider(`customProvider${i}`, htmlData)); + providers.push(newHTMLDataProvider(`customProvider${i}`, htmlData)); } } catch (err) { console.log(`Failed to load tag from ${path}`); diff --git a/extensions/html-language-features/server/src/htmlServerMain.ts b/extensions/html-language-features/server/src/htmlServerMain.ts index 43ae7d5070c..7974284bd77 100644 --- a/extensions/html-language-features/server/src/htmlServerMain.ts +++ b/extensions/html-language-features/server/src/htmlServerMain.ts @@ -455,15 +455,15 @@ connection.onFoldingRanges((params, token) => { }, null, `Error while computing folding regions for ${params.textDocument.uri}`, token); }); -connection.onRequest('$/textDocument/selectionRange', async (params, token) => { +connection.onRequest('$/textDocument/selectionRanges', async (params, token) => { return runSafe(() => { const document = documents.get(params.textDocument.uri); - const position: Position = params.position; + const positions: Position[] = params.positions; if (document) { const htmlMode = languageModes.getMode('html'); - if (htmlMode && htmlMode.doSelection) { - return htmlMode.doSelection(document, position); + if (htmlMode && htmlMode.getSelectionRanges) { + return htmlMode.getSelectionRanges(document, positions); } } return Promise.resolve(null); diff --git a/extensions/html-language-features/server/src/modes/htmlMode.ts b/extensions/html-language-features/server/src/modes/htmlMode.ts index 00a690f56eb..09efb996f6e 100644 --- a/extensions/html-language-features/server/src/modes/htmlMode.ts +++ b/extensions/html-language-features/server/src/modes/htmlMode.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { getLanguageModelCache } from '../languageModelCache'; -import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration } from 'vscode-html-languageservice'; +import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration, SelectionRange } from 'vscode-html-languageservice'; import { TextDocument, Position, Range, CompletionItem, FoldingRange } from 'vscode-languageserver-types'; import { LanguageMode, Workspace } from './languageModes'; import { getPathCompletionParticipant } from './pathCompletion'; @@ -15,8 +15,8 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace: getId() { return 'html'; }, - doSelection(document: TextDocument, position: Position): Range[] { - return htmlLanguageService.getSelectionRanges(document, position); + getSelectionRanges(document: TextDocument, positions: Position[]): SelectionRange[][] { + return htmlLanguageService.getSelectionRanges(document, positions); }, doComplete(document: TextDocument, position: Position, settings = workspace.settings) { let options = settings && settings.html && settings.html.suggest; diff --git a/extensions/html-language-features/server/src/modes/languageModes.ts b/extensions/html-language-features/server/src/modes/languageModes.ts index 048076ed70d..94c0b04a293 100644 --- a/extensions/html-language-features/server/src/modes/languageModes.ts +++ b/extensions/html-language-features/server/src/modes/languageModes.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getLanguageService as getHTMLLanguageService, DocumentContext, IHTMLDataProvider } from 'vscode-html-languageservice'; +import { getLanguageService as getHTMLLanguageService, DocumentContext, IHTMLDataProvider, SelectionRange } from 'vscode-html-languageservice'; import { CompletionItem, Location, SignatureHelp, Definition, TextEdit, TextDocument, Diagnostic, DocumentLink, Range, Hover, DocumentHighlight, CompletionList, Position, FormattingOptions, SymbolInformation, FoldingRange @@ -31,7 +31,7 @@ export interface Workspace { export interface LanguageMode { getId(): string; - doSelection?: (document: TextDocument, position: Position) => Range[]; + getSelectionRanges?: (document: TextDocument, positions: Position[]) => SelectionRange[][]; doValidation?: (document: TextDocument, settings?: Settings) => Diagnostic[]; doComplete?: (document: TextDocument, position: Position, settings?: Settings) => CompletionList; doResolve?: (document: TextDocument, item: CompletionItem) => CompletionItem; diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index 5173fd2b003..79eeb0196cb 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -229,20 +229,20 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^3.0.13-next.10: - version "3.0.13-next.10" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-3.0.13-next.10.tgz#f5822e832b06e1e91ec96c528bab83bb07251c35" - integrity sha512-zKwzo3GVhrAllYDM4afL8q1XCHixsI8tP3SyLrWGzp0Nc9P+bbjKQeC26VcaOb0dtkgfpB/vfBPf+4yOs4s/pw== +vscode-css-languageservice@^4.0.0-next.3: + version "4.0.0-next.3" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.0-next.3.tgz#e9529f3b4ddf95c9a3e5dc2a6d701a38280ffa98" + integrity sha512-/xmbWpIQLw+HZ/3LsaE2drHFSNJbM9mZ8bKR5NUiu2ZUr10WbGxX0j/GDZB3LlMmdSHQGgRQ5hTM/Ic2PuBDRw== dependencies: - vscode-languageserver-types "^3.13.0" + vscode-languageserver-types "^3.14.0" vscode-nls "^4.0.0" -vscode-html-languageservice@^2.1.11: - version "2.1.11" - resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-2.1.11.tgz#56fc25cf64793a9eaef2f571a0ecd591eaed26c1" - integrity sha512-wfENgWb7JjEhwsRHXhairumuxAGnFcMUwIut5P7SxGwNrJMDXkgfs6OUBZycQpbaXTkMEvwsKNKFqUQppW7P4g== +vscode-html-languageservice@^3.0.0-next.3: + version "3.0.0-next.3" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.0-next.3.tgz#a0230c57375deb21fadbfa0210a770ca6e06d425" + integrity sha512-vPdZ17JSr8kAAnjNjdiH4jYySaJrXqnbT3OhnGXqc51R3jnwMXV/Jf72ctXptbpiUQM3ifHnfUcxwO+34tw6Lw== dependencies: - vscode-languageserver-types "^3.13.0" + vscode-languageserver-types "^3.14.0" vscode-nls "^4.0.0" vscode-uri "^1.0.6" @@ -251,25 +251,25 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.15.0-next.1: + version "3.15.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.1.tgz#1e45e224d7eef8c79b4bed75b9dcb1930d2ab8ed" + integrity sha512-LXF0d9s3vxFBxVQ4aKl/XghdEMAncGt3dh4urIYa9Is43g3MfIQL9fC44YZtP+XXOrI2rpZU8lRNN01U1V6CDg== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0, vscode-languageserver-types@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0, vscode-languageserver-types@^3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== -vscode-languageserver@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz#012a28f154cc7a848c443d217894942e4c3eeb39" - integrity sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw== +vscode-languageserver@^5.3.0-next.2: + version "5.3.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.2.tgz#31ce4c34d68b517b400ca9e211e43f8d868b8dcc" + integrity sha512-n5onRw9naMrRHp2jnOn+ZwN1n+tTfzftWLPonjp1FWf/iCZWIlnw2TyF/Hn+SDGhLoVtoghmxhwEQaxEAfLHvw== dependencies: - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.15.0-next.1" vscode-uri "^1.0.6" vscode-nls@^4.0.0: diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index 2737f409efa..a0667775d59 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -45,26 +45,26 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageclient@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz#650ab0dc9fd0daaade058a8471aaff5bc3f9580e" - integrity sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg== +vscode-languageclient@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz#7cfc83a294c409f58cfa2b910a8cfeaad0397193" + integrity sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q== dependencies: semver "^5.5.0" - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.14.1" -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f" + integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== vscode-nls@^4.0.0: version "4.0.0" From ce3f0c17d7cce900a9c6ab9053f981809e1dcd95 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 5 Mar 2019 15:27:46 +0100 Subject: [PATCH 063/172] [json] update service (webpack) --- .../json-language-features/package.json | 4 +- .../server/build/filesFillIn.js | 5 -- .../server/extension.webpack.config.js | 4 -- .../server/package.json | 6 +-- .../json-language-features/server/yarn.lock | 48 +++++++++---------- extensions/json-language-features/yarn.lock | 28 +++++------ 6 files changed, 43 insertions(+), 52 deletions(-) delete mode 100644 extensions/json-language-features/server/build/filesFillIn.js diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index 47d1f7bf32d..4cd6d425a76 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -102,10 +102,10 @@ }, "dependencies": { "vscode-extension-telemetry": "0.1.1", - "vscode-languageclient": "^5.1.0", + "vscode-languageclient": "^5.2.1", "vscode-nls": "^4.0.0" }, "devDependencies": { "@types/node": "^10.12.21" } -} \ No newline at end of file +} diff --git a/extensions/json-language-features/server/build/filesFillIn.js b/extensions/json-language-features/server/build/filesFillIn.js deleted file mode 100644 index 906617384e0..00000000000 --- a/extensions/json-language-features/server/build/filesFillIn.js +++ /dev/null @@ -1,5 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -module.exports = {}; \ No newline at end of file diff --git a/extensions/json-language-features/server/extension.webpack.config.js b/extensions/json-language-features/server/extension.webpack.config.js index b31abe55f25..9c605f6b5ae 100644 --- a/extensions/json-language-features/server/extension.webpack.config.js +++ b/extensions/json-language-features/server/extension.webpack.config.js @@ -21,10 +21,6 @@ module.exports = withDefaults({ path: path.join(__dirname, 'dist') }, plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), new webpack.IgnorePlugin(/vertx/) ], }); diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 959af9a9794..fc2323a773e 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -12,10 +12,10 @@ }, "main": "./out/jsonServerMain", "dependencies": { - "jsonc-parser": "^2.0.2", + "jsonc-parser": "^2.0.3", "request-light": "^0.2.4", - "vscode-json-languageservice": "^3.3.0-next.4", - "vscode-languageserver": "^5.1.0", + "vscode-json-languageservice": "^3.3.0-next.6", + "vscode-languageserver": "^5.3.0-next.2", "vscode-nls": "^4.0.0", "vscode-uri": "^1.0.6" }, diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index 7a974ff4a2b..bb8489b6d86 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -54,10 +54,10 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" -jsonc-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.0.2.tgz#42fcf56d70852a043fadafde51ddb4a85649978d" - integrity sha512-TSU435K5tEKh3g7bam1AFf+uZrISheoDsLlpmAo6wWZYqjsnd09lHYK1Qo+moK4Ikifev1Gdpa69g4NELKnCrQ== +jsonc-parser@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.0.3.tgz#6d4199ccab7f21ff5d2a4225050c54e981fb21a2" + integrity sha512-WJi9y9ABL01C8CxTKxRRQkkSpY/x2bo4Gy0WuiZGrInxQqgxQpvkBCLNcDYcHOSdhx4ODgbFcgAvfL49C+PHgQ== ms@2.0.0: version "2.0.0" @@ -73,13 +73,13 @@ request-light@^0.2.4: https-proxy-agent "^2.2.1" vscode-nls "^4.0.0" -vscode-json-languageservice@^3.3.0-next.4: - version "3.3.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.0-next.4.tgz#e13b2fd5665b754ee94608a506407cd12b63d64d" - integrity sha512-tD8w2SvwERj3392q34xXKA/i76WWK7YwmP9eoLdKvdfMRwXB7a0MYWPoYZD4HycwvavAlbJ2x18vP4G7+BFA+A== +vscode-json-languageservice@^3.3.0-next.6: + version "3.3.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.0-next.6.tgz#711f121b44ba443a89f3fb01a01c611f2547079f" + integrity sha512-i1tyLiodWc7y6lR9C4cat+OUSptj8Duk1Ybm1FaMzhNfOTFttSiwrBw1otNb+QwI65VEj7EAEBQHRLeQOWznMw== dependencies: - jsonc-parser "^2.0.2" - vscode-languageserver-types "^3.13.0" + jsonc-parser "^2.0.3" + vscode-languageserver-types "^3.14.0" vscode-nls "^4.0.0" vscode-uri "^1.0.6" @@ -88,25 +88,25 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.15.0-next.1: + version "3.15.0-next.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.1.tgz#1e45e224d7eef8c79b4bed75b9dcb1930d2ab8ed" + integrity sha512-LXF0d9s3vxFBxVQ4aKl/XghdEMAncGt3dh4urIYa9Is43g3MfIQL9fC44YZtP+XXOrI2rpZU8lRNN01U1V6CDg== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0, vscode-languageserver-types@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0, vscode-languageserver-types@^3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== -vscode-languageserver@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz#012a28f154cc7a848c443d217894942e4c3eeb39" - integrity sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw== +vscode-languageserver@^5.3.0-next.2: + version "5.3.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.2.tgz#31ce4c34d68b517b400ca9e211e43f8d868b8dcc" + integrity sha512-n5onRw9naMrRHp2jnOn+ZwN1n+tTfzftWLPonjp1FWf/iCZWIlnw2TyF/Hn+SDGhLoVtoghmxhwEQaxEAfLHvw== dependencies: - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.15.0-next.1" vscode-uri "^1.0.6" vscode-nls@^4.0.0: diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index e49fc01bd24..9315ad7e193 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -50,26 +50,26 @@ vscode-jsonrpc@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== -vscode-languageclient@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz#650ab0dc9fd0daaade058a8471aaff5bc3f9580e" - integrity sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg== +vscode-languageclient@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz#7cfc83a294c409f58cfa2b910a8cfeaad0397193" + integrity sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q== dependencies: semver "^5.5.0" - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "3.14.1" -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f" + integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g== dependencies: vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "3.14.0" -vscode-languageserver-types@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" + integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== vscode-nls@^4.0.0: version "4.0.0" From f0983abe97e10cacd98f27dc4c8f219eb857e8ce Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Mar 2019 15:39:36 +0100 Subject: [PATCH 064/172] Fix #69681 --- src/tsconfig.strictNullChecks.json | 1 + src/vs/workbench/common/editor.ts | 4 +- .../electron-browser/preferencesSearch.ts | 39 +----- .../preferences/browser/preferencesService.ts | 117 ++++++++++-------- .../preferences/common/preferences.ts | 16 +-- .../common/preferencesEditorInput.ts | 2 +- .../preferences/common/preferencesModels.ts | 75 +++++------ .../test/common/preferencesModel.test.ts | 10 +- 8 files changed, 130 insertions(+), 134 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 7bed7f931fe..9bdb62faf4d 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -28,6 +28,7 @@ "./vs/workbench/services/themes/**/*.ts", "./vs/workbench/services/bulkEdit/**/*.ts", "./vs/workbench/services/progress/**/*.ts", + "./vs/workbench/services/preferences/**/*.ts", "./vs/workbench/services/timer/**/*.ts" ], "files": [ diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 6a016bc91cc..eb745aa83fc 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -533,7 +533,7 @@ export class SideBySideEditorInput extends EditorInput { static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; - constructor(private name: string, private description: string, private _details: EditorInput, private _master: EditorInput) { + constructor(private name: string, private description: string | null, private _details: EditorInput, private _master: EditorInput) { super(); this.registerListeners(); @@ -602,7 +602,7 @@ export class SideBySideEditorInput extends EditorInput { return this.name; } - getDescription(): string { + getDescription(): string | null { return this.description; } diff --git a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts index 4edd06ce8e7..9c34a8343f5 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts @@ -23,6 +23,7 @@ import { IPreferencesSearchService, ISearchProvider, IWorkbenchSettingsConfigura import { CancellationToken } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; import { ExtensionType } from 'vs/platform/extensions/common/extensions'; +import { nullRange } from 'vs/workbench/services/preferences/common/preferencesModels'; export interface IEndpointDetails { urlBase: string; @@ -426,12 +427,12 @@ function remoteSettingToISetting(remoteSetting: IRemoteSetting): IExtensionSetti return { description: remoteSetting.description.split('\n'), descriptionIsMarkdown: false, - descriptionRanges: null, + descriptionRanges: [], key: remoteSetting.key, - keyRange: null, + keyRange: nullRange, value: remoteSetting.defaultValue, - range: null, - valueRange: null, + range: nullRange, + valueRange: nullRange, overrides: [], extensionName: remoteSetting.extensionName, extensionPublisher: remoteSetting.extensionPublisher @@ -536,16 +537,6 @@ class SettingMatches { } private toKeyRange(setting: ISetting, match: IMatch): IRange { - if (!setting.keyRange) { - // No source range? Return fake range, don't care - return { - startLineNumber: 0, - startColumn: 0, - endLineNumber: 0, - endColumn: 0, - }; - } - return { startLineNumber: setting.keyRange.startLineNumber, startColumn: setting.keyRange.startColumn + match.start, @@ -555,16 +546,6 @@ class SettingMatches { } private toDescriptionRange(setting: ISetting, match: IMatch, lineIndex: number): IRange { - if (!setting.keyRange) { - // No source range? Return fake range, don't care - return { - startLineNumber: 0, - startColumn: 0, - endLineNumber: 0, - endColumn: 0, - }; - } - return { startLineNumber: setting.descriptionRanges[lineIndex].startLineNumber, startColumn: setting.descriptionRanges[lineIndex].startColumn + match.start, @@ -574,16 +555,6 @@ class SettingMatches { } private toValueRange(setting: ISetting, match: IMatch): IRange { - if (!setting.keyRange) { - // No source range? Return fake range, don't care - return { - startLineNumber: 0, - startColumn: 0, - endLineNumber: 0, - endColumn: 0, - }; - } - return { startLineNumber: setting.valueRange.startLineNumber, startColumn: setting.valueRange.startColumn + match.start + 1, diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index e5cd0c64ab7..744146bb756 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -89,10 +89,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic private readonly defaultSettingsRawResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/defaultSettings.json' }); get userSettingsResource(): URI { - return this.getEditableSettingsURI(ConfigurationTarget.USER); + return this.getEditableSettingsURI(ConfigurationTarget.USER)!; } - get workspaceSettingsResource(): URI { + get workspaceSettingsResource(): URI | null { return this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE); } @@ -100,11 +100,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.instantiationService.createInstance(SettingsEditor2Input); } - getFolderSettingsResource(resource: URI): URI { + getFolderSettingsResource(resource: URI): URI | null { return this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, resource); } - resolveModel(uri: URI): Promise { + resolveModel(uri: URI): Promise { if (this.isDefaultSettingsResource(uri)) { const target = this.getConfigurationTargetFromDefaultSettingsResource(uri); @@ -156,7 +156,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.createDefaultSettingsEditorModel(uri); } - if (this.getEditableSettingsURI(ConfigurationTarget.USER).toString() === uri.toString()) { + if (this.userSettingsResource.toString() === uri.toString()) { return this.createEditableSettingsEditorModel(ConfigurationTarget.USER, uri); } @@ -169,7 +169,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE_FOLDER, uri); } - return Promise.resolve>(null); + return Promise.reject(`unknown resource: ${uri.toString()}`); } openRawDefaultSettings(): Promise { @@ -190,7 +190,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } const editorInput = this.getActiveSettingsEditorInput() || this.lastOpenedSettingsInput; - const resource = editorInput ? editorInput.master.getResource() : this.userSettingsResource; + const resource = editorInput ? editorInput.master.getResource()! : this.userSettingsResource; const target = this.getConfigurationTargetFromSettingsResource(resource); return this.openOrSwitchSettings(target, resource); } @@ -198,7 +198,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic private openSettings2(): Promise { const input = this.settingsEditor2Input; return this.editorGroupService.activeGroup.openEditor(input) - .then(() => this.editorGroupService.activeGroup.activeControl); + .then(() => this.editorGroupService.activeGroup.activeControl!); } openGlobalSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { @@ -211,14 +211,14 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.openOrSwitchSettings2(ConfigurationTarget.USER, undefined, options, group); } - openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + if (!this.workspaceSettingsResource) { this.notificationService.info(nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); - return Promise.resolve(null); + return Promise.reject(null); } return jsonEditor ? @@ -230,22 +230,26 @@ export class PreferencesService extends Disposable implements IPreferencesServic jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; - - return jsonEditor ? - this.openOrSwitchSettings(ConfigurationTarget.WORKSPACE_FOLDER, this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder), options, group) : - this.openOrSwitchSettings2(ConfigurationTarget.WORKSPACE_FOLDER, folder, options, group); + const folderSettingsUri = this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder); + if (jsonEditor) { + if (folderSettingsUri) { + return this.openOrSwitchSettings(ConfigurationTarget.WORKSPACE_FOLDER, folderSettingsUri, options, group); + } + return Promise.reject(`Invalid folder URI - ${folder.toString()}`); + } + return this.openOrSwitchSettings2(ConfigurationTarget.WORKSPACE_FOLDER, folder, options, group); } switchSettings(target: ConfigurationTarget, resource: URI, jsonEditor?: boolean): Promise { if (!jsonEditor) { - return this.doOpenSettings2(target, resource).then(() => null); + return this.doOpenSettings2(target, resource).then(() => undefined); } const activeControl = this.editorService.activeControl; if (activeControl && activeControl.input instanceof PreferencesEditorInput) { - return this.doSwitchSettings(target, resource, activeControl.input, activeControl.group).then(() => null); + return this.doSwitchSettings(target, resource, activeControl.input, activeControl.group).then(() => undefined); } else { - return this.doOpenSettings(target, resource).then(() => null); + return this.doOpenSettings(target, resource).then(() => undefined); } } @@ -276,7 +280,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } - return this.editorService.openEditor(this.instantiationService.createInstance(KeybindingsEditorInput), { pinned: true, revealIfOpened: true }).then(() => null); + return this.editorService.openEditor(this.instantiationService.createInstance(KeybindingsEditorInput), { pinned: true, revealIfOpened: true }).then(() => undefined); } openDefaultKeybindingsFile(): Promise { @@ -291,7 +295,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic if (codeEditor) { this.addLanguageOverrideEntry(language, settingsModel, codeEditor) .then(position => { - if (codeEditor) { + if (codeEditor && position) { codeEditor.setPosition(position); codeEditor.revealLine(position.lineNumber); codeEditor.focus(); @@ -303,8 +307,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic private openOrSwitchSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group: IEditorGroup = this.editorGroupService.activeGroup): Promise { const editorInput = this.getActiveSettingsEditorInput(group); - if (editorInput && editorInput.master.getResource().fsPath !== resource.fsPath) { - return this.doSwitchSettings(configurationTarget, resource, editorInput, group, options); + if (editorInput) { + const editorInputResource = editorInput.master.getResource(); + if (editorInputResource && editorInputResource.fsPath !== resource.fsPath) { + return this.doSwitchSettings(configurationTarget, resource, editorInput, group, options); + } } return this.doOpenSettings(configurationTarget, resource, options, group); } @@ -335,7 +342,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return Promise.all([ this.editorService.openEditor({ resource: this.defaultSettingsRawResource, options: { pinned: true, preserveFocus: true, revealIfOpened: true }, label: nls.localize('defaultSettings', "Default Settings"), description: '' }), this.editorService.openEditor(editableSettingsEditorInput, { pinned: true, revealIfOpened: true }, sideEditorGroup.id) - ]).then(() => null); + ]).then(([defaultEditor, editor]) => editor); } else { return this.editorService.openEditor(editableSettingsEditorInput, SettingsEditorOptions.create(options), group); } @@ -374,7 +381,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private doSwitchSettings(target: ConfigurationTarget, resource: URI, input: PreferencesEditorInput, group: IEditorGroup, options?: ISettingsEditorOptions): Promise { - return this.getOrCreateEditableSettingsEditorInput(target, this.getEditableSettingsURI(target, resource)) + const settingsURI = this.getEditableSettingsURI(target, resource); + if (!settingsURI) { + return Promise.reject(`Invalid settings URI - ${resource.toString()}`); + } + return this.getOrCreateEditableSettingsEditorInput(target, settingsURI) .then(toInput => { return group.openEditor(input).then(() => { const replaceWith = new PreferencesEditorInput(this.getPreferencesEditorInputName(target, resource), toInput.getDescription(), this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(target)), toInput); @@ -382,10 +393,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic return group.replaceEditors([{ editor: input, replacement: replaceWith, - options: SettingsEditorOptions.create(options) + options: options ? SettingsEditorOptions.create(options) : undefined }]).then(() => { this.lastOpenedSettingsInput = replaceWith; - return group.activeControl; + return group.activeControl!; }); }); }); @@ -464,7 +475,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.textModelResolverService.createModelReference(settingsUri) .then(reference => this.instantiationService.createInstance(SettingsEditorModel, reference, configurationTarget)); } - return Promise.resolve(null); + return Promise.reject(`unknown target: ${configurationTarget} and resource: ${resource.toString()}`); } private createDefaultSettingsEditorModel(defaultSettingsUri: URI): Promise { @@ -494,7 +505,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this._defaultUserSettingsContentModel; } - private getEditableSettingsURI(configurationTarget: ConfigurationTarget, resource?: URI): URI { + private getEditableSettingsURI(configurationTarget: ConfigurationTarget, resource?: URI): URI | null { switch (configurationTarget) { case ConfigurationTarget.USER: return URI.file(this.environmentService.appSettingsPath); @@ -505,8 +516,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic const workspace = this.contextService.getWorkspace(); return workspace.configuration || workspace.folders[0].toResource(FOLDER_SETTINGS_PATH); case ConfigurationTarget.WORKSPACE_FOLDER: - const folder = this.contextService.getWorkspaceFolder(resource); - return folder ? folder.toResource(FOLDER_SETTINGS_PATH) : null; + if (resource) { + const folder = this.contextService.getWorkspaceFolder(resource); + return folder ? folder.toResource(FOLDER_SETTINGS_PATH) : null; + } } return null; } @@ -523,7 +536,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic if (Object.keys(parse(content.value)).indexOf('settings') === -1) { return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(undefined, () => { }); } - return null; + return undefined; }); } return this.createIfNotExists(resource, emptyEditableSettingsContent).then(() => { }); @@ -557,29 +570,35 @@ export class PreferencesService extends Disposable implements IPreferencesServic ]; } - private addLanguageOverrideEntry(language: string, settingsModel: IPreferencesEditorModel, codeEditor: ICodeEditor): Promise { + private addLanguageOverrideEntry(language: string, settingsModel: IPreferencesEditorModel, codeEditor: ICodeEditor): Promise { const languageKey = `[${language}]`; let setting = settingsModel.getPreference(languageKey); const model = codeEditor.getModel(); - const configuration = this.configurationService.getValue<{ editor: { tabSize: number; insertSpaces: boolean } }>(); - const eol = model.getEOL(); - if (setting) { - if (setting.overrides.length) { - const lastSetting = setting.overrides[setting.overrides.length - 1]; - return Promise.resolve({ lineNumber: lastSetting.valueRange.endLineNumber, column: model.getLineMaxColumn(lastSetting.valueRange.endLineNumber) }); + if (model) { + const configuration = this.configurationService.getValue<{ editor: { tabSize: number; insertSpaces: boolean } }>(); + const eol = model.getEOL(); + if (setting) { + if (setting.overrides && setting.overrides.length) { + const lastSetting = setting.overrides[setting.overrides.length - 1]; + return Promise.resolve({ lineNumber: lastSetting.valueRange.endLineNumber, column: model.getLineMaxColumn(lastSetting.valueRange.endLineNumber) }); + } + return Promise.resolve({ lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 }); } - return Promise.resolve({ lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 }); + return this.configurationService.updateValue(languageKey, {}, ConfigurationTarget.USER) + .then(() => { + setting = settingsModel.getPreference(languageKey); + if (setting) { + let content = eol + this.spaces(2, configuration.editor) + eol + this.spaces(1, configuration.editor); + let editOperation = EditOperation.insert(new Position(setting.valueRange.endLineNumber, setting.valueRange.endColumn - 1), content); + model.pushEditOperations([], [editOperation], () => []); + let lineNumber = setting.valueRange.endLineNumber + 1; + settingsModel.dispose(); + return { lineNumber, column: model.getLineMaxColumn(lineNumber) }; + } + return null; + }); } - return this.configurationService.updateValue(languageKey, {}, ConfigurationTarget.USER) - .then(() => { - setting = settingsModel.getPreference(languageKey); - let content = eol + this.spaces(2, configuration.editor) + eol + this.spaces(1, configuration.editor); - let editOperation = EditOperation.insert(new Position(setting.valueRange.endLineNumber, setting.valueRange.endColumn - 1), content); - model.pushEditOperations([], [editOperation], () => []); - let lineNumber = setting.valueRange.endLineNumber + 1; - settingsModel.dispose(); - return { lineNumber, column: model.getLineMaxColumn(lineNumber) }; - }); + return Promise.resolve(null); } private spaces(count: number, { tabSize, insertSpaces }: { tabSize: number; insertSpaces: boolean }): string { diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 4bf2e5500f5..b1d1d0a4a99 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -53,7 +53,7 @@ export interface ISetting { value: any; valueRange: IRange; description: string[]; - descriptionIsMarkdown: boolean; + descriptionIsMarkdown?: boolean; descriptionRanges: IRange[]; overrides?: ISetting[]; overrideOf?: ISetting; @@ -65,7 +65,7 @@ export interface ISetting { enumDescriptions?: string[]; enumDescriptionsAreMarkdown?: boolean; tags?: string[]; - validator?: (value: any) => string; + validator?: (value: any) => string | null; } export interface IExtensionSetting extends ISetting { @@ -162,11 +162,7 @@ export class SettingsEditorOptions extends EditorOptions implements ISettingsEdi folderUri?: URI; query?: string; - static create(settings: ISettingsEditorOptions): SettingsEditorOptions | null { - if (!settings) { - return null; - } - + static create(settings: ISettingsEditorOptions): SettingsEditorOptions { const options = new SettingsEditorOptions(); options.target = settings.target; @@ -195,10 +191,10 @@ export interface IPreferencesService { _serviceBrand: any; userSettingsResource: URI; - workspaceSettingsResource: URI; - getFolderSettingsResource(resource: URI): URI; + workspaceSettingsResource: URI | null; + getFolderSettingsResource(resource: URI): URI | null; - resolveModel(uri: URI): Promise; + resolveModel(uri: URI): Promise; createPreferencesEditorModel(uri: URI): Promise>; createSettings2EditorModel(): Settings2EditorModel; // TODO diff --git a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts index 4929b15f8f9..e1db37ca23b 100644 --- a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts +++ b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts @@ -22,7 +22,7 @@ export class PreferencesEditorInput extends SideBySideEditorInput { return PreferencesEditorInput.ID; } - getTitle(verbosity: Verbosity): string { + getTitle(verbosity: Verbosity): string | null { return this.master.getTitle(verbosity); } } diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index f61324585e4..1c7936e9096 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -23,6 +23,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { EditorModel } from 'vs/workbench/common/editor'; import { IFilterMetadata, IFilterResult, IGroupFilter, IKeybindingsEditorModel, ISearchResultGroup, ISetting, ISettingMatch, ISettingMatcher, ISettingsEditorModel, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; +export const nullRange: IRange = { startLineNumber: -1, startColumn: -1, endLineNumber: -1, endColumn: -1 }; +export function isNullRange(range: IRange): boolean { return range.startLineNumber === -1 && range.startColumn === -1 && range.endLineNumber === -1 && range.endColumn === -1; } + export abstract class AbstractSettingsModel extends EditorModel { protected _currentResultGroups = new Map(); @@ -124,7 +127,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti constructor(reference: IReference, private _configurationTarget: ConfigurationTarget) { super(); - this.settingsModel = reference.object.textEditorModel; + this.settingsModel = reference.object.textEditorModel!; this._register(this.onDispose(() => reference.dispose())); this._register(this.settingsModel.onDidChangeContent(() => { this._settingsGroups = null; @@ -268,7 +271,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, } if (previousParents.length === settingsPropertyIndex + 1 || (previousParents.length === settingsPropertyIndex + 2 && overrideSetting !== null)) { // settings value started - const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1]; + const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1]; if (setting) { const valueStartPosition = model.getPositionAt(offset); const valueEndPosition = model.getPositionAt(offset + length); @@ -288,7 +291,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, } const visitor: JSONVisitor = { onObjectBegin: (offset: number, length: number) => { - if (isSettingsProperty(currentProperty, previousParents)) { + if (isSettingsProperty(currentProperty!, previousParents)) { // Settings started settingsPropertyIndex = previousParents.length; const position = model.getPositionAt(offset); @@ -323,10 +326,10 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, endColumn: 0 }, value: null, - valueRange: null, - descriptionRanges: null, + valueRange: nullRange, + descriptionRanges: [], overrides: [], - overrideOf: overrideSetting + overrideOf: overrideSetting || undefined }; if (previousParents.length === settingsPropertyIndex + 1) { settings.push(setting); @@ -334,7 +337,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, overrideSetting = setting; } } else { - overrideSetting.overrides.push(setting); + overrideSetting!.overrides!.push(setting); } } }, @@ -342,7 +345,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, currentParent = previousParents.pop(); if (previousParents.length === settingsPropertyIndex + 1 || (previousParents.length === settingsPropertyIndex + 2 && overrideSetting !== null)) { // setting ended - const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1]; + const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1]; if (setting) { const valueEndPosition = model.getPositionAt(offset + length); setting.valueRange = assign(setting.valueRange, { @@ -377,7 +380,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, currentParent = previousParents.pop(); if (previousParents.length === settingsPropertyIndex + 1 || (previousParents.length === settingsPropertyIndex + 2 && overrideSetting !== null)) { // setting value ended - const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1]; + const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1]; if (setting) { const valueEndPosition = model.getPositionAt(offset + length); setting.valueRange = assign(setting.valueRange, { @@ -394,7 +397,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, onLiteralValue: onValue, onError: (error) => { const setting = settings[settings.length - 1]; - if (setting && (!setting.range || !setting.keyRange || !setting.valueRange)) { + if (setting && (isNullRange(setting.range) || isNullRange(setting.keyRange) || isNullRange(setting.valueRange))) { settings.pop(); } } @@ -408,8 +411,8 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, settings } ], - title: null, - titleRange: null, + title: '', + titleRange: nullRange, range }] : []; } @@ -514,13 +517,15 @@ export class DefaultSettings extends Disposable { description: setting.description, key: setting.key, value: setting.value, - range: null, - valueRange: null, + keyRange: nullRange, + range: nullRange, + valueRange: nullRange, overrides: [], scope: ConfigurationScope.RESOURCE, type: setting.type, enum: setting.enum, - enumDescriptions: setting.enumDescriptions + enumDescriptions: setting.enumDescriptions, + descriptionRanges: [] }; } return null; @@ -528,9 +533,9 @@ export class DefaultSettings extends Disposable { return { id: 'mostCommonlyUsed', - range: null, + range: nullRange, title: nls.localize('commonlyUsed', "Commonly Used"), - titleRange: null, + titleRange: nullRange, sections: [ { settings @@ -552,7 +557,7 @@ export class DefaultSettings extends Disposable { if (!settingsGroup) { settingsGroup = find(result, g => g.title === title); if (!settingsGroup) { - settingsGroup = { sections: [{ settings: [] }], id: config.id, title: title, titleRange: null, range: null, contributedByExtension: !!config.contributedByExtension }; + settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: title || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.contributedByExtension }; result.push(settingsGroup); } } else { @@ -561,7 +566,7 @@ export class DefaultSettings extends Disposable { } if (config.properties) { if (!settingsGroup) { - settingsGroup = { sections: [{ settings: [] }], id: config.id, title: config.id, titleRange: null, range: null, contributedByExtension: !!config.contributedByExtension }; + settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: config.id || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.contributedByExtension }; result.push(settingsGroup); } const configurationSettings: ISetting[] = []; @@ -605,9 +610,9 @@ export class DefaultSettings extends Disposable { value, description, descriptionIsMarkdown: !prop.description, - range: null, - keyRange: null, - valueRange: null, + range: nullRange, + keyRange: nullRange, + valueRange: nullRange, descriptionRanges: [], overrides, scope: prop.scope, @@ -630,9 +635,9 @@ export class DefaultSettings extends Disposable { value: overrideSettings[key], description: [], descriptionIsMarkdown: false, - range: null, - keyRange: null, - valueRange: null, + range: nullRange, + keyRange: nullRange, + valueRange: nullRange, descriptionRanges: [], overrides: [] })); @@ -691,7 +696,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements super(); this._register(defaultSettings.onDidChange(() => this._onDidChangeGroups.fire())); - this._model = reference.object.textEditorModel; + this._model = reference.object.textEditorModel!; this._register(this.onDispose(() => reference.dispose())); } @@ -712,7 +717,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements return this.settingsGroups.slice(1); } - protected update(): IFilterResult { + protected update(): IFilterResult | null { if (this._model.isDisposed()) { return null; } @@ -825,10 +830,10 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements overrideOf: setting.overrideOf, tags: setting.tags, deprecationMessage: setting.deprecationMessage, - keyRange: undefined, - valueRange: undefined, + keyRange: nullRange, + valueRange: nullRange, descriptionIsMarkdown: undefined, - descriptionRanges: undefined + descriptionRanges: [] }; } @@ -852,9 +857,9 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements private getGroup(resultGroup: ISearchResultGroup): ISettingsGroup { return { id: resultGroup.id, - range: null, + range: nullRange, title: resultGroup.label, - titleRange: null, + titleRange: nullRange, sections: [ { settings: resultGroup.result.filterMatches.map(m => this.copySetting(m.setting)) @@ -899,7 +904,7 @@ class SettingsContentBuilder { this._contentByLines.push('}'); } - protected _pushGroup(group: ISettingsGroup, indent: string): ISetting { + protected _pushGroup(group: ISettingsGroup, indent: string): ISetting | null { let lastSetting: ISetting | null = null; const groupStart = this.lineCountWithOffset + 1; for (const section of group.sections) { @@ -959,7 +964,7 @@ class SettingsContentBuilder { if (setting.enumDescriptions && setting.enumDescriptions.some(desc => !!desc)) { setting.enumDescriptions.forEach((desc, i) => { - const displayEnum = escapeInvisibleChars(String(setting.enum[i])); + const displayEnum = escapeInvisibleChars(String(setting.enum![i])); const line = desc ? `${displayEnum}: ${fixSettingLink(desc)}` : displayEnum; @@ -974,7 +979,7 @@ class SettingsContentBuilder { private pushValue(setting: ISetting, preValueConent: string, indent: string): void { const valueString = JSON.stringify(setting.value, null, indent); if (valueString && (typeof setting.value === 'object')) { - if (setting.overrides.length) { + if (setting.overrides && setting.overrides.length) { this._contentByLines.push(preValueConent + ' {'); for (const subSetting of setting.overrides) { this.pushSetting(subSetting, indent + indent); diff --git a/src/vs/workbench/services/preferences/test/common/preferencesModel.test.ts b/src/vs/workbench/services/preferences/test/common/preferencesModel.test.ts index d4dae17cbc3..c428209859a 100644 --- a/src/vs/workbench/services/preferences/test/common/preferencesModel.test.ts +++ b/src/vs/workbench/services/preferences/test/common/preferencesModel.test.ts @@ -10,7 +10,7 @@ import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/c suite('Preferences Model test', () => { class Tester { - private validator: (value: any) => string; + private validator: (value: any) => string | null; constructor(private settings: IConfigurationPropertySchema) { this.validator = createValidator(settings)!; @@ -24,8 +24,12 @@ suite('Preferences Model test', () => { assert.notEqual(this.validator(input), '', `Expected ${JSON.stringify(this.settings)} to reject \`${input}\`.`); return { withMessage: - (message) => assert(this.validator(input).indexOf(message) > -1, - `Expected error of ${JSON.stringify(this.settings)} on \`${input}\` to contain ${message}. Got ${this.validator(input)}.`) + (message) => { + const actual = this.validator(input); + assert.ok(actual); + assert(actual!.indexOf(message) > -1, + `Expected error of ${JSON.stringify(this.settings)} on \`${input}\` to contain ${message}. Got ${this.validator(input)}.`); + } }; } From c6315a3d30771ff83bb6cf56528404859f25a9e4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 16:07:41 +0100 Subject: [PATCH 065/172] debt - more services cleanup --- src/vs/platform/lifecycle/common/lifecycle.ts | 2 +- .../workbench/electron-browser/workbench.ts | 88 ++++++++++--------- .../services/backup/node/backupFileService.ts | 67 +++++++++++++- .../backupFileService.test.ts | 22 ++++- src/vs/workbench/workbench.main.ts | 1 + 5 files changed, 134 insertions(+), 46 deletions(-) diff --git a/src/vs/platform/lifecycle/common/lifecycle.ts b/src/vs/platform/lifecycle/common/lifecycle.ts index 4879ee13e8d..18782a0d0b3 100644 --- a/src/vs/platform/lifecycle/common/lifecycle.ts +++ b/src/vs/platform/lifecycle/common/lifecycle.ts @@ -133,7 +133,7 @@ export interface ILifecycleService { /** * A flag indicating in what phase of the lifecycle we currently are. */ - readonly phase: LifecyclePhase; + phase: LifecyclePhase; /** * Fired before shutdown happens. Allows listeners to veto against the diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index b1e469d99db..0625ab7372a 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -105,8 +105,6 @@ import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; // import@node -import { BackupFileService, InMemoryBackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc'; import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc'; @@ -190,13 +188,13 @@ export class Workbench extends Disposable implements IPartService { private editorService: EditorService; private editorGroupService: IEditorGroupsService; private contextViewService: ContextViewService; - private backupFileService: IBackupFileService; private windowService: IWindowService; - private lifecycleService: LifecycleService; + private lifecycleService: ILifecycleService; + private instantiationService: IInstantiationService; private contextService: IWorkspaceContextService; private storageService: IStorageService; - private configurationService: WorkspaceService; + private configurationService: IConfigurationService; private environmentService: IEnvironmentService; private logService: ILogService; private windowsService: IWindowsService; @@ -221,7 +219,7 @@ export class Workbench extends Disposable implements IPartService { @IInstantiationService instantiationService: IInstantiationService, @IWorkspaceContextService contextService: IWorkspaceContextService, @IStorageService storageService: IStorageService, - @IConfigurationService configurationService: WorkspaceService, + @IConfigurationService configurationService: IConfigurationService, @IEnvironmentService environmentService: IEnvironmentService, @ILogService logService: ILogService, @IWindowsService windowsService: IWindowsService @@ -333,7 +331,7 @@ export class Workbench extends Disposable implements IPartService { this.registerLayoutListeners(); // Layout State - this.initLayoutState(); + this.instantiationService.invokeFunction(accessor => this.initLayoutState(accessor)); // Render Workbench this.renderWorkbench(); @@ -525,14 +523,6 @@ export class Workbench extends Disposable implements IPartService { // History serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService)); - // Backup File Service - if (this.configuration.backupPath) { - this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.configuration.backupPath); - } else { - this.backupFileService = new InMemoryBackupFileService(); - } - serviceCollection.set(IBackupFileService, this.backupFileService); - // Quick open service (quick open controller) this.quickOpen = this.instantiationService.createInstance(QuickOpenController); serviceCollection.set(IQuickOpenService, this.quickOpen); @@ -561,12 +551,20 @@ export class Workbench extends Disposable implements IPartService { this.instantiationService.invokeFunction(accessor => { const fileService = accessor.get(IFileService); const instantiationService = accessor.get(IInstantiationService); - const themeService = accessor.get(IWorkbenchThemeService) as WorkbenchThemeService; + const configurationService = accessor.get(IConfigurationService) as any; + const themeService = accessor.get(IWorkbenchThemeService) as any; - this.configurationService.acquireFileService(fileService); - this.configurationService.acquireInstantiationService(instantiationService); + if (typeof configurationService.acquireFileService === 'function') { + configurationService.acquireFileService(fileService); + } - themeService.acquireFileService(fileService); + if (typeof configurationService.acquireInstantiationService === 'function') { + configurationService.acquireInstantiationService(instantiationService); + } + + if (typeof themeService.acquireFileService === 'function') { + themeService.acquireFileService(fileService); + } }); } @@ -785,7 +783,7 @@ export class Workbench extends Disposable implements IPartService { } private whenStarted(accessor: ServicesAccessor, error?: Error): void { - const lifecycleService = accessor.get(ILifecycleService) as LifecycleService; + const lifecycleService = accessor.get(ILifecycleService); this.restored = true; @@ -1020,22 +1018,27 @@ export class Workbench extends Disposable implements IPartService { } } - private initLayoutState(): void { + private initLayoutState(accessor: ServicesAccessor): void { + const configurationService = accessor.get(IConfigurationService); + const storageService = accessor.get(IStorageService); + const lifecycleService = accessor.get(ILifecycleService); + const contextService = accessor.get(IWorkspaceContextService); + const environmentService = accessor.get(IEnvironmentService); // Fullscreen this.state.fullscreen = isFullscreen(); // Menubar visibility - this.state.menuBar.visibility = this.configurationService.getValue(Settings.MENUBAR_VISIBLE); + this.state.menuBar.visibility = configurationService.getValue(Settings.MENUBAR_VISIBLE); // Activity bar visibility - this.state.activityBar.hidden = !this.configurationService.getValue(Settings.ACTIVITYBAR_VISIBLE); + this.state.activityBar.hidden = !configurationService.getValue(Settings.ACTIVITYBAR_VISIBLE); // Sidebar visibility - this.state.sideBar.hidden = this.storageService.getBoolean(Storage.SIDEBAR_HIDDEN, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY); + this.state.sideBar.hidden = storageService.getBoolean(Storage.SIDEBAR_HIDDEN, StorageScope.WORKSPACE, contextService.getWorkbenchState() === WorkbenchState.EMPTY); // Sidebar position - this.state.sideBar.position = (this.configurationService.getValue(Settings.SIDEBAR_POSITION) === 'right') ? Position.RIGHT : Position.LEFT; + this.state.sideBar.position = (configurationService.getValue(Settings.SIDEBAR_POSITION) === 'right') ? Position.RIGHT : Position.LEFT; // Sidebar viewlet if (!this.state.sideBar.hidden) { @@ -1043,8 +1046,8 @@ export class Workbench extends Disposable implements IPartService { // Only restore last viewlet if window was reloaded or we are in development mode let viewletToRestore: string; - if (!this.environmentService.isBuilt || this.lifecycleService.startupKind === StartupKind.ReloadedWindow) { - viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, viewletRegistry.getDefaultViewletId()); + if (!environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow) { + viewletToRestore = storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, viewletRegistry.getDefaultViewletId()); } else { viewletToRestore = viewletRegistry.getDefaultViewletId(); } @@ -1057,13 +1060,13 @@ export class Workbench extends Disposable implements IPartService { } // Editor centered layout - this.state.editor.restoreCentered = this.storageService.getBoolean(Storage.CENTERED_LAYOUT_ENABLED, StorageScope.WORKSPACE, false); + this.state.editor.restoreCentered = storageService.getBoolean(Storage.CENTERED_LAYOUT_ENABLED, StorageScope.WORKSPACE, false); // Editors to open - this.state.editor.editorsToOpen = this.resolveEditorsToOpen(); + this.state.editor.editorsToOpen = this.resolveEditorsToOpen(accessor); // Panel visibility - this.state.panel.hidden = this.storageService.getBoolean(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE, true); + this.state.panel.hidden = storageService.getBoolean(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE, true); // Panel position this.updatePanelPosition(); @@ -1072,7 +1075,7 @@ export class Workbench extends Disposable implements IPartService { if (!this.state.panel.hidden) { const panelRegistry = Registry.as(PanelExtensions.Panels); - let panelToRestore = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId()); + let panelToRestore = storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId()); if (!panelRegistry.hasPanel(panelToRestore)) { panelToRestore = panelRegistry.getDefaultPanelId(); // fallback to default if panel is unknown } @@ -1085,19 +1088,24 @@ export class Workbench extends Disposable implements IPartService { } // Statusbar visibility - this.state.statusBar.hidden = !this.configurationService.getValue(Settings.STATUSBAR_VISIBLE); + this.state.statusBar.hidden = !configurationService.getValue(Settings.STATUSBAR_VISIBLE); // Zen mode enablement - this.state.zenMode.restore = this.storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && this.configurationService.getValue(Settings.ZEN_MODE_RESTORE); + this.state.zenMode.restore = storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && configurationService.getValue(Settings.ZEN_MODE_RESTORE); } - private resolveEditorsToOpen(): Promise | IResourceEditor[] { + private resolveEditorsToOpen(accessor: ServicesAccessor): Promise | IResourceEditor[] { + const configuration = accessor.get(IWindowService).getConfiguration(); + const configurationService = accessor.get(IConfigurationService); + const contextService = accessor.get(IWorkspaceContextService); + const editorGroupService = accessor.get(IEditorGroupsService); + const backupFileService = accessor.get(IBackupFileService); // Files to open, diff or create if (this.hasInitialFilesToOpen()) { // Files to diff is exclusive - const filesToDiff = this.toInputs(this.configuration.filesToDiff, false); + const filesToDiff = this.toInputs(configuration.filesToDiff, false); if (filesToDiff && filesToDiff.length === 2) { return [{ leftResource: filesToDiff[0].resource, @@ -1107,21 +1115,21 @@ export class Workbench extends Disposable implements IPartService { }]; } - const filesToCreate = this.toInputs(this.configuration.filesToCreate, true); - const filesToOpen = this.toInputs(this.configuration.filesToOpen, false); + const filesToCreate = this.toInputs(configuration.filesToCreate, true); + const filesToOpen = this.toInputs(configuration.filesToOpen, false); // Otherwise: Open/Create files return [...filesToOpen, ...filesToCreate]; } // Empty workbench - else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.configurationService.inspect('workbench.startupEditor').value === 'newUntitledFile') { - const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0; + else if (contextService.getWorkbenchState() === WorkbenchState.EMPTY && configurationService.inspect('workbench.startupEditor').value === 'newUntitledFile') { + const isEmpty = editorGroupService.count === 1 && editorGroupService.activeGroup.count === 0; if (!isEmpty) { return []; // do not open any empty untitled file if we restored editors from previous session } - return this.backupFileService.hasBackups().then(hasBackups => { + return backupFileService.hasBackups().then(hasBackups => { if (hasBackups) { return []; // do not open any empty untitled file if we have backups to restore } diff --git a/src/vs/workbench/services/backup/node/backupFileService.ts b/src/vs/workbench/services/backup/node/backupFileService.ts index a089102b7f9..5eb3e0402c5 100644 --- a/src/vs/workbench/services/backup/node/backupFileService.ts +++ b/src/vs/workbench/services/backup/node/backupFileService.ts @@ -15,6 +15,8 @@ import { ITextBufferFactory } from 'vs/editor/common/model'; import { createTextBufferFactoryFromStream, createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; import { keys } from 'vs/base/common/map'; import { Schemas } from 'vs/base/common/network'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; export interface IBackupFilesModel { resolve(backupRoot: string): Promise; @@ -107,6 +109,63 @@ export class BackupFilesModel implements IBackupFilesModel { export class BackupFileService implements IBackupFileService { + _serviceBrand: any; + + private impl: IBackupFileService; + + constructor( + @IWindowService windowService: IWindowService, + @IFileService fileService: IFileService + ) { + const backupWorkspacePath = windowService.getConfiguration().backupPath; + if (backupWorkspacePath) { + this.impl = new BackupFileServiceImpl(backupWorkspacePath, fileService); + } else { + this.impl = new InMemoryBackupFileService(); + } + } + + initialize(backupWorkspacePath: string): void { + if (this.impl instanceof BackupFileServiceImpl) { + this.impl.initialize(backupWorkspacePath); + } + } + + hasBackups(): Promise { + return this.impl.hasBackups(); + } + + loadBackupResource(resource: Uri): Promise { + return this.impl.loadBackupResource(resource); + } + + backupResource(resource: Uri, content: ITextSnapshot, versionId?: number): Promise { + return this.impl.backupResource(resource, content, versionId); + } + + discardResourceBackup(resource: Uri): Promise { + return this.impl.discardResourceBackup(resource); + } + + discardAllWorkspaceBackups(): Promise { + return this.impl.discardAllWorkspaceBackups(); + } + + getWorkspaceFileBackups(): Promise { + return this.impl.getWorkspaceFileBackups(); + } + + resolveBackupContent(backup: Uri): Promise { + return this.impl.resolveBackupContent(backup); + } + + toBackupResource(resource: Uri): Uri { + return this.impl.toBackupResource(resource); + } +} + +class BackupFileServiceImpl implements IBackupFileService { + private static readonly META_MARKER = '\n'; _serviceBrand: any; @@ -170,7 +229,7 @@ export class BackupFileService implements IBackupFileService { } return this.ioOperationQueues.queueFor(backupResource).queue(() => { - const preamble = `${resource.toString()}${BackupFileService.META_MARKER}`; + const preamble = `${resource.toString()}${BackupFileServiceImpl.META_MARKER}`; // Update content with value return this.fileService.updateContent(backupResource, new BackupSnapshot(content, preamble), BACKUP_FILE_UPDATE_OPTIONS).then(() => model.add(backupResource, versionId)); @@ -202,7 +261,7 @@ export class BackupFileService implements IBackupFileService { model.get().forEach(fileBackup => { readPromises.push( - readToMatchingString(fileBackup.fsPath, BackupFileService.META_MARKER, 2000, 10000).then(Uri.parse) + readToMatchingString(fileBackup.fsPath, BackupFileServiceImpl.META_MARKER, 2000, 10000).then(Uri.parse) ); }); @@ -217,7 +276,7 @@ export class BackupFileService implements IBackupFileService { let metaFound = false; const metaPreambleFilter = (chunk: string) => { if (!metaFound && chunk) { - const metaIndex = chunk.indexOf(BackupFileService.META_MARKER); + const metaIndex = chunk.indexOf(BackupFileServiceImpl.META_MARKER); if (metaIndex === -1) { return ''; // meta not yet found, return empty string } @@ -302,3 +361,5 @@ export function hashPath(resource: Uri): string { const str = resource.scheme === Schemas.file ? resource.fsPath : resource.toString(); return crypto.createHash('md5').update(str).digest('hex'); } + +registerSingleton(IBackupFileService, BackupFileService); \ No newline at end of file diff --git a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts index 5f1ea987873..d2d9a82d2c2 100644 --- a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts @@ -13,7 +13,7 @@ import { URI as Uri } from 'vs/base/common/uri'; import { BackupFileService, BackupFilesModel, hashPath } from 'vs/workbench/services/backup/node/backupFileService'; import { FileService } from 'vs/workbench/services/files/node/fileService'; import { TextModel, createTextBufferFactory } from 'vs/editor/common/model/textModel'; -import { TestContextService, TestTextResourceConfigurationService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestContextService, TestTextResourceConfigurationService, TestLifecycleService, TestEnvironmentService, TestStorageService, TestWindowService } from 'vs/workbench/test/workbenchTestServices'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; @@ -21,6 +21,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/ import { DefaultEndOfLine } from 'vs/editor/common/model'; import { snapshotToString } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); const backupHome = path.join(parentDir, 'Backups'); @@ -35,11 +36,28 @@ const fooBackupPath = path.join(workspaceBackupPath, 'file', hashPath(fooFile)); const barBackupPath = path.join(workspaceBackupPath, 'file', hashPath(barFile)); const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', hashPath(untitledFile)); +class TestBackupWindowService extends TestWindowService { + + private config: IWindowConfiguration; + + constructor(workspaceBackupPath: string) { + super(); + + this.config = Object.create(null); + this.config.backupPath = workspaceBackupPath; + } + + getConfiguration(): IWindowConfiguration { + return this.config; + } +} + class TestBackupFileService extends BackupFileService { constructor(workspace: Uri, backupHome: string, workspacesJsonPath: string) { const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, toWorkspaceFolders([{ path: workspace.fsPath }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true }); + const windowService = new TestBackupWindowService(workspaceBackupPath); - super(workspaceBackupPath, fileService); + super(windowService, fileService); } public toBackupResource(resource: Uri): Uri { diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index ceffd2a8727..e06ec70c0b0 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -73,6 +73,7 @@ import 'vs/workbench/services/configuration/node/jsonEditingService'; import 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import 'vs/workbench/services/textfile/common/textFileService'; import 'vs/workbench/services/dialogs/electron-browser/dialogService'; +import 'vs/workbench/services/backup/node/backupFileService'; registerSingleton(IMenuService, MenuService, true); registerSingleton(IListService, ListService, true); From 849d9417eab3d8f85792070247bdc99247ce174a Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 5 Mar 2019 16:26:43 +0100 Subject: [PATCH 066/172] [json] fetch http and https schemas on the ext host --- .../client/src/jsonMain.ts | 24 +++++-- .../extension.webpack.config.js | 7 +- .../json-language-features/package.json | 3 +- .../server/extension.webpack.config.js | 4 +- extensions/json-language-features/yarn.lock | 68 +++++++++++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) diff --git a/extensions/json-language-features/client/src/jsonMain.ts b/extensions/json-language-features/client/src/jsonMain.ts index 30b122071b1..ee52e73fc61 100644 --- a/extensions/json-language-features/client/src/jsonMain.ts +++ b/extensions/json-language-features/client/src/jsonMain.ts @@ -6,6 +6,8 @@ import * as path from 'path'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; +import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light'; + const localize = nls.loadMessageBundle(); import { workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, Diagnostic, StatusBarAlignment, TextEditor, TextDocument, Position, SelectionRange } from 'vscode'; @@ -93,6 +95,9 @@ export function activate(context: ExtensionContext) { let clientOptions: LanguageClientOptions = { // Register the server for json documents documentSelector, + initializationOptions: { + handledSchemaProtocols: ['file'] // language server only loads file-URI. Fetching schemas with other protocols ('http'...) are made on the client. + }, synchronize: { // Synchronize the setting section 'json' to the server configurationSection: ['json', 'http'], @@ -138,11 +143,20 @@ export function activate(context: ExtensionContext) { // handle content request client.onRequest(VSCodeContentRequest.type, (uriPath: string) => { let uri = Uri.parse(uriPath); - return workspace.openTextDocument(uri).then(doc => { - return doc.getText(); - }, error => { - return Promise.reject(error); - }); + if (uri.scheme !== 'http' && uri.scheme !== 'https') { + return workspace.openTextDocument(uri).then(doc => { + return doc.getText(); + }, error => { + return Promise.reject(error); + }); + } else { + const headers = { 'Accept-Encoding': 'gzip, deflate' }; + return xhr({ url: uriPath, followRedirects: 5, headers }).then(response => { + return response.responseText; + }, (error: XHRResponse) => { + return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); + }); + } }); let handleContentChange = (uri: Uri) => { diff --git a/extensions/json-language-features/extension.webpack.config.js b/extensions/json-language-features/extension.webpack.config.js index 4c2ab99cf25..bf887a3d0d8 100644 --- a/extensions/json-language-features/extension.webpack.config.js +++ b/extensions/json-language-features/extension.webpack.config.js @@ -9,6 +9,7 @@ const withDefaults = require('../shared.webpack.config'); const path = require('path'); +var webpack = require('webpack'); module.exports = withDefaults({ context: path.join(__dirname, 'client'), @@ -18,5 +19,9 @@ module.exports = withDefaults({ output: { filename: 'jsonMain.js', path: path.join(__dirname, 'client', 'dist') - } + }, + plugins: [ + new webpack.IgnorePlugin(/vertx/) // request-light dependendeny + ] + }); diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index 4cd6d425a76..9dc4f87d9f0 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -103,7 +103,8 @@ "dependencies": { "vscode-extension-telemetry": "0.1.1", "vscode-languageclient": "^5.2.1", - "vscode-nls": "^4.0.0" + "vscode-nls": "^4.0.0", + "request-light": "^0.2.4" }, "devDependencies": { "@types/node": "^10.12.21" diff --git a/extensions/json-language-features/server/extension.webpack.config.js b/extensions/json-language-features/server/extension.webpack.config.js index 9c605f6b5ae..e6f4c516bc9 100644 --- a/extensions/json-language-features/server/extension.webpack.config.js +++ b/extensions/json-language-features/server/extension.webpack.config.js @@ -21,6 +21,6 @@ module.exports = withDefaults({ path: path.join(__dirname, 'dist') }, plugins: [ - new webpack.IgnorePlugin(/vertx/) - ], + new webpack.IgnorePlugin(/vertx/) // request-light dependendeny + ] }); diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index 9315ad7e193..758f96fd511 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -7,6 +7,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.21.tgz#7e8a0c34cf29f4e17a36e9bd0ea72d45ba03908e" integrity sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ== +agent-base@4, agent-base@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -16,6 +23,20 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" +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" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -28,6 +49,53 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" +es6-promise@^4.0.3: + version "4.2.6" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" + integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + dependencies: + agent-base "^4.1.0" + debug "^3.1.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== + +request-light@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.4.tgz#3cea29c126682e6bcadf7915353322eeba01a755" + integrity sha512-pM9Fq5jRnSb+82V7M97rp8FE9/YNeP2L9eckB4Szd7lyeclSIx02aIpPO/6e4m6Dy31+FBN/zkFMTd2HkNO3ow== + dependencies: + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + vscode-nls "^4.0.0" + semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" From 66b45946a1ce68c0b4774d1772fb6707906b858d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 16:33:39 +0100 Subject: [PATCH 067/172] fix strict null --- src/vs/workbench/services/backup/node/backupFileService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/backup/node/backupFileService.ts b/src/vs/workbench/services/backup/node/backupFileService.ts index 5eb3e0402c5..396f9acb3ce 100644 --- a/src/vs/workbench/services/backup/node/backupFileService.ts +++ b/src/vs/workbench/services/backup/node/backupFileService.ts @@ -155,7 +155,7 @@ export class BackupFileService implements IBackupFileService { return this.impl.getWorkspaceFileBackups(); } - resolveBackupContent(backup: Uri): Promise { + resolveBackupContent(backup: Uri): Promise { return this.impl.resolveBackupContent(backup); } From a40b2ae4d87a4450471bfe7b6795180a7704b252 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 16:38:37 +0100 Subject: [PATCH 068/172] :lipstick: --- src/vs/workbench/services/backup/node/backupFileService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/services/backup/node/backupFileService.ts b/src/vs/workbench/services/backup/node/backupFileService.ts index 396f9acb3ce..61fafbaa6f6 100644 --- a/src/vs/workbench/services/backup/node/backupFileService.ts +++ b/src/vs/workbench/services/backup/node/backupFileService.ts @@ -351,7 +351,6 @@ export class InMemoryBackupFileService implements IBackupFileService { toBackupResource(resource: Uri): Uri { return Uri.file(path.join(resource.scheme, hashPath(resource))); } - } /* From b5b811980f1b4f147b4fdea6a22b56359fe09783 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Mar 2019 15:59:59 +0100 Subject: [PATCH 069/172] Remove IWorkspaceConfigurationService --- .../api/electron-browser/mainThreadConfiguration.ts | 5 ++--- src/vs/workbench/browser/parts/editor/editorStatus.ts | 7 +++---- .../contrib/feedback/electron-browser/feedback.ts | 4 ++-- .../feedback/electron-browser/feedbackStatusbarItem.ts | 7 +++---- .../preferences/electron-browser/preferencesSearch.ts | 4 ++-- .../contrib/terminal/browser/terminalConfigHelper.ts | 3 +-- .../contrib/terminal/browser/terminalProcessManager.ts | 4 ++-- .../contrib/themes/browser/themes.contribution.ts | 7 +++---- .../electron-browser/actions/windowActions.ts | 10 +++++----- src/vs/workbench/electron-browser/window.ts | 4 ++-- .../services/configuration/common/configuration.ts | 8 -------- .../configuration/node/configurationService.ts | 6 +++--- .../test/electron-browser/configurationService.test.ts | 5 ++--- .../services/preferences/browser/preferencesService.ts | 5 ++--- .../services/workspace/node/workspaceEditingService.ts | 4 ++-- 15 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 495b36864ad..4947445ffe3 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -8,10 +8,9 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, getScopes } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import { ConfigurationTarget, IConfigurationChangeEvent, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationChangeEvent, IConfigurationModel, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @extHostNamedCustomer(MainContext.MainThreadConfiguration) @@ -22,7 +21,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { constructor( extHostContext: IExtHostContext, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, ) { const proxy = extHostContext.getProxy(ExtHostContext.ExtHostConfiguration); diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index a8542918815..cee38df5af8 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -26,7 +26,6 @@ import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/bina import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { SUPPORTED_ENCODINGS, IFileService, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService'; @@ -40,7 +39,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { IConfigurationChangedEvent, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { deepClone } from 'vs/base/common/objects'; import { ICodeEditor, isCodeEditor, isDiffEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { Schemas } from 'vs/base/common/network'; @@ -293,7 +292,7 @@ export class EditorStatus implements IStatusbarItem { @IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService, @IModeService private readonly modeService: IModeService, @ITextFileService private readonly textFileService: ITextFileService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @INotificationService private readonly notificationService: INotificationService, @IAccessibilityService private readonly accessibilityService: IAccessibilityService ) { @@ -845,7 +844,7 @@ export class ChangeModeAction extends Action { @IModeService private readonly modeService: IModeService, @IModelService private readonly modelService: IModelService, @IEditorService private readonly editorService: IEditorService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @IQuickInputService private readonly quickInputService: IQuickInputService, @IPreferencesService private readonly preferencesService: IPreferencesService, @IInstantiationService private readonly instantiationService: IInstantiationService, diff --git a/src/vs/workbench/contrib/feedback/electron-browser/feedback.ts b/src/vs/workbench/contrib/feedback/electron-browser/feedback.ts index 9175a111ac2..51c206a57f7 100644 --- a/src/vs/workbench/contrib/feedback/electron-browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/electron-browser/feedback.ts @@ -15,10 +15,10 @@ import { IIntegrityService } from 'vs/workbench/services/integrity/common/integr import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { attachButtonStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { editorWidgetBackground, widgetShadow, inputBorder, inputForeground, inputBackground, inputActiveOptionBorder, editorBackground, buttonBackground, contrastBorder, darken } from 'vs/platform/theme/common/colorRegistry'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; import { Button } from 'vs/base/browser/ui/button/button'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export const FEEDBACK_VISIBLE_CONFIG = 'workbench.statusBar.feedback.visible'; @@ -66,7 +66,7 @@ export class FeedbackDropdown extends Dropdown { @ITelemetryService private readonly telemetryService: ITelemetryService, @IIntegrityService private readonly integrityService: IIntegrityService, @IThemeService private readonly themeService: IThemeService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(container, { contextViewProvider: options.contextViewProvider, diff --git a/src/vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts index d03f6921014..7a904adc838 100644 --- a/src/vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts @@ -12,8 +12,7 @@ import product from 'vs/platform/product/node/product'; import { Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND } from 'vs/workbench/common/theme'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { clearNode, EventHelper, addClass, removeClass, addDisposableListener } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; @@ -62,7 +61,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { @IContextViewService private readonly contextViewService: IContextViewService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IContextMenuService private readonly contextMenuService: IContextMenuService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @IThemeService themeService: IThemeService ) { super(themeService); @@ -155,7 +154,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { class HideAction extends Action { constructor( - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super('feedback.hide', localize('hide', "Hide")); } diff --git a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts index 9c34a8343f5..c72c3d6c1ee 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts @@ -11,7 +11,6 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IRequestService } from 'vs/platform/request/node/request'; @@ -24,6 +23,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { nullRange } from 'vs/workbench/services/preferences/common/preferencesModels'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export interface IEndpointDetails { urlBase: string; @@ -36,7 +36,7 @@ export class PreferencesSearchService extends Disposable implements IPreferences private _installedExtensions: Promise; constructor( - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index f4f0476caa0..506ceef0bf0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -8,7 +8,6 @@ import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITerminalConfiguration, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; @@ -33,7 +32,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { public constructor( private readonly _linuxDistro: LinuxDistro, @IConfigurationService private readonly _configurationService: IConfigurationService, - @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly _workspaceConfigurationService: IConfigurationService, @INotificationService private readonly _notificationService: INotificationService, @IStorageService private readonly _storageService: IStorageService ) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 18d6d58d78b..432d886e99f 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -18,10 +18,10 @@ import { IWindowService } from 'vs/platform/windows/common/windows'; import { Schemas } from 'vs/base/common/network'; import { REMOTE_HOST_SCHEME, getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IProductService } from 'vs/platform/product/common/product'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -61,7 +61,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWindowService private readonly _windowService: IWindowService, - @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly _workspaceConfigurationService: IConfigurationService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, @IProductService private readonly _productService: IProductService, @ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 47a9776b807..10167ea1196 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -15,11 +15,10 @@ import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/contrib/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 { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; 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'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { LIGHT, DARK, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; import { colorThemeSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -37,7 +36,7 @@ export class SelectColorThemeAction extends Action { @IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @IViewletService private readonly viewletService: IViewletService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(id, label); } @@ -98,7 +97,7 @@ class SelectIconThemeAction extends Action { @IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @IViewletService private readonly viewletService: IViewletService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(id, label); diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-browser/actions/windowActions.ts index ef640150e1f..ea55154a0ad 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-browser/actions/windowActions.ts @@ -10,7 +10,6 @@ import { Action } from 'vs/base/common/actions'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import * as nls from 'vs/nls'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { isMacintosh } from 'vs/base/common/platform'; import * as browser from 'vs/base/browser/browser'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -27,6 +26,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import product from 'vs/platform/product/node/product'; import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class CloseCurrentWindowAction extends Action { @@ -82,7 +82,7 @@ export abstract class BaseZoomAction extends Action { constructor( id: string, label: string, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService ) { super(id, label); } @@ -111,7 +111,7 @@ export class ZoomInAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService + @IConfigurationService configurationService: IConfigurationService ) { super(id, label, configurationService); } @@ -131,7 +131,7 @@ export class ZoomOutAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService + @IConfigurationService configurationService: IConfigurationService ) { super(id, label, configurationService); } @@ -151,7 +151,7 @@ export class ZoomResetAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService + @IConfigurationService configurationService: IConfigurationService ) { super(id, label, configurationService); } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index acb68c8ad71..0ca278cc10b 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -14,7 +14,6 @@ import { IFileService } from 'vs/platform/files/common/files'; import { toResource, IUntitledResourceInput } from 'vs/workbench/common/editor'; import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IWindowsService, IWindowService, IWindowSettings, IOpenFileRequest, IWindowsConfiguration, IAddFoldersRequest, IRunActionInWindowRequest, IPathData, IRunKeybindingInWindowRequest } from 'vs/platform/windows/common/windows'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITitleService } from 'vs/workbench/services/title/common/titleService'; @@ -43,6 +42,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { coalesce } from 'vs/base/common/arrays'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; const TextInputActions: IAction[] = [ new Action('undo', nls.localize('undo', "Undo"), undefined, true, () => Promise.resolve(document.execCommand('undo'))), @@ -75,7 +75,7 @@ export class ElectronWindow extends Disposable { @IEditorService private readonly editorService: EditorServiceImpl, @IWindowsService private readonly windowsService: IWindowsService, @IWindowService private readonly windowService: IWindowService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @ITitleService private readonly titleService: ITitleService, @IWorkbenchThemeService protected themeService: IWorkbenchThemeService, @INotificationService private readonly notificationService: INotificationService, diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index 344bfa78905..ad2658aa60e 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -3,18 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; - export const FOLDER_CONFIG_FOLDER_NAME = '.vscode'; export const FOLDER_SETTINGS_NAME = 'settings'; export const FOLDER_SETTINGS_PATH = `${FOLDER_CONFIG_FOLDER_NAME}/${FOLDER_SETTINGS_NAME}.json`; -export const IWorkspaceConfigurationService = createDecorator('configurationService'); - -export interface IWorkspaceConfigurationService extends IConfigurationService { -} - export const defaultSettingsSchemaId = 'vscode://schemas/settings/default'; export const userSettingsSchemaId = 'vscode://schemas/settings/user'; export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace'; diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index b71054c6318..61a17082dca 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -17,9 +17,9 @@ import { isLinux } from 'vs/base/common/platform'; import { IFileService } from 'vs/platform/files/common/files'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; -import { IWorkspaceConfigurationService, FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationNode, IConfigurationRegistry, Extensions, IConfigurationPropertySchema, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; @@ -37,7 +37,7 @@ import { isEqual, dirname } from 'vs/base/common/resources'; import { mark } from 'vs/base/common/performance'; import { Schemas } from 'vs/base/common/network'; -export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { +export class WorkspaceService extends Disposable implements IConfigurationService, IWorkspaceContextService { public _serviceBrand: any; diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 5e78dc69c52..d7e050e7a94 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -31,7 +31,6 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { createHash } from 'crypto'; import { Emitter, Event } from 'vs/base/common/event'; import { Schemas } from 'vs/base/common/network'; @@ -697,7 +696,7 @@ suite('WorkspaceService - Initialization', () => { suite('WorkspaceConfigurationService - Folder', () => { - let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IWorkspaceConfigurationService, globalSettingsFile: string; + let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); suiteSetup(() => { @@ -983,7 +982,7 @@ suite('WorkspaceConfigurationService - Folder', () => { suite('WorkspaceConfigurationService-Multiroot', () => { - let parentResource: string, workspaceContextService: IWorkspaceContextService, environmentService: IEnvironmentService, jsonEditingServce: IJSONEditingService, testObject: IWorkspaceConfigurationService; + let parentResource: string, workspaceContextService: IWorkspaceContextService, environmentService: IEnvironmentService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); suiteSetup(() => { diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index 744146bb756..8efc41d7c34 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -18,7 +18,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import * as nls from 'vs/nls'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; @@ -29,7 +29,6 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { EditorInput, IEditor } from 'vs/workbench/common/editor'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { GroupDirection, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -59,7 +58,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic @IEditorService private readonly editorService: IEditorService, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, @IFileService private readonly fileService: IFileService, - @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly configurationService: IConfigurationService, @INotificationService private readonly notificationService: INotificationService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IInstantiationService private readonly instantiationService: IInstantiationService, diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index a1884b928a5..ac34d2b1ae2 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -10,7 +10,6 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { IWindowService, MessageBoxOptions, IWindowsService } from 'vs/platform/windows/common/windows'; import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, isWorkspaceIdentifier, toWorkspaceIdentifier, IWorkspacesService, rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/common/workspaces'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { StorageService } from 'vs/platform/storage/node/storageService'; @@ -27,6 +26,7 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/ import { IFileService } from 'vs/platform/files/common/files'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -36,7 +36,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { @IJSONEditingService private readonly jsonEditingService: IJSONEditingService, @IWorkspaceContextService private readonly contextService: WorkspaceService, @IWindowService private readonly windowService: IWindowService, - @IWorkspaceConfigurationService private readonly workspaceConfigurationService: IWorkspaceConfigurationService, + @IConfigurationService private readonly workspaceConfigurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, @IExtensionService private readonly extensionService: IExtensionService, @IBackupFileService private readonly backupFileService: IBackupFileService, From fc277b039ba07ed734ee15b37869bd86f8ae1403 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 5 Mar 2019 16:56:01 +0100 Subject: [PATCH 070/172] Fix #69521 --- src/vs/workbench/browser/parts/compositeBarActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 54c9a40efa7..6e59e616bcd 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -252,9 +252,9 @@ export class ActivityActionItem extends BaseActionItem { const noOfThousands = badge.number / 1000; const floor = Math.floor(noOfThousands); if (noOfThousands > floor) { - number = nls.localize('largeNumberBadge1', '{0}k+', floor); + number = `${floor}K+`; } else { - number = nls.localize('largeNumberBadge2', '{0}k', noOfThousands); + number = `${noOfThousands}K`; } } this.badgeContent.textContent = number; From bf9a27ec01f2ef82fc45f69e0c946c7d74a57d3e Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Mar 2019 17:06:11 +0100 Subject: [PATCH 071/172] [Debug] Filter "Call Stack" panel based on thread state fixes #69793 --- src/vs/workbench/contrib/debug/common/debug.ts | 2 ++ src/vs/workbench/contrib/debug/common/debugModel.ts | 9 +++++++++ .../contrib/debug/electron-browser/callStackView.ts | 10 ++-------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 89c6088288c..e303532fc05 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -246,6 +246,8 @@ export interface IThread extends ITreeElement { */ readonly exceptionInfo: Promise; + readonly stateLabel: string; + /** * Gets the callstack if it has already been received from the debug * adapter, otherwise it returns null. diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 36f80abb7f8..91422072397 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -418,6 +418,15 @@ export class Thread implements IThread { return this.staleCallStack; } + get stateLabel(): string { + if (this.stopped) { + return this.stoppedDetails.description || + this.stoppedDetails.reason ? nls.localize({ key: 'pausedOn', comment: ['indicates reason for program being paused'] }, "Paused on {0}", this.stoppedDetails.reason) : nls.localize('paused', "Paused"); + } + + return nls.localize({ key: 'running', comment: ['indicates state'] }, "Running"); + } + /** * Queries the debug adapter for the callstack and returns a promise * which completes once the call stack has been retrieved. diff --git a/src/vs/workbench/contrib/debug/electron-browser/callStackView.ts b/src/vs/workbench/contrib/debug/electron-browser/callStackView.ts index dc153ca4e0e..ff9c117f7e5 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/callStackView.ts @@ -133,7 +133,7 @@ export class CallStackView extends ViewletPanel { return e.getLabel(); } if (e instanceof Thread) { - return e.name; + return `${e.name} ${e.stateLabel}`; } if (e instanceof StackFrame || typeof e === 'string') { return e; @@ -410,13 +410,7 @@ class ThreadsRenderer implements ITreeRenderer Date: Tue, 5 Mar 2019 18:17:47 +0100 Subject: [PATCH 072/172] fixes #68549 --- src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index 5137f89c2c5..fbb1c4db32f 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -410,7 +410,7 @@ export class BulkEditService implements IBulkEditService { } } - const bulkEdit = new BulkEdit(codeEditor, options.progress, this._logService, this._textModelService, this._fileService, this._textFileService, this._labelService, this._configurationService); + const bulkEdit = new BulkEdit(options.editor, options.progress, this._logService, this._textModelService, this._fileService, this._textFileService, this._labelService, this._configurationService); bulkEdit.add(edits); return bulkEdit.perform().then(() => { From 2f0fdae41d44c1f87bf3b0877c625d170dfdba22 Mon Sep 17 00:00:00 2001 From: Adam Tajti Date: Tue, 5 Mar 2019 18:37:24 +0100 Subject: [PATCH 073/172] Cleanup: Remove duplicate configuration from outline.contribution.ts --- .../contrib/outline/browser/outline.contribution.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index a53f3eae4d7..7ac9a19b96f 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -41,11 +41,6 @@ Registry.as(ConfigurationExtensions.Configuration).regis 'type': 'boolean', 'default': true }, - [OutlineConfigKeys.problemsEnabled]: { - 'description': localize('outline.showProblem', "Show Errors & Warnings on Outline Elements."), - 'type': 'boolean', - 'default': true - }, [OutlineConfigKeys.problemsColors]: { 'description': localize('outline.problem.colors', "Use colors for Errors & Warnings."), 'type': 'boolean', From 1251a5094d8433ae6c081d86304f6910b3ab1e12 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 5 Mar 2019 18:39:12 +0100 Subject: [PATCH 074/172] Revert "fixes #68549" This reverts commit a3817504c42c073a8ff2ad2d87801ac8339e754d. --- src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index fbb1c4db32f..5137f89c2c5 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -410,7 +410,7 @@ export class BulkEditService implements IBulkEditService { } } - const bulkEdit = new BulkEdit(options.editor, options.progress, this._logService, this._textModelService, this._fileService, this._textFileService, this._labelService, this._configurationService); + const bulkEdit = new BulkEdit(codeEditor, options.progress, this._logService, this._textModelService, this._fileService, this._textFileService, this._labelService, this._configurationService); bulkEdit.add(edits); return bulkEdit.perform().then(() => { From 4a8d7b7080d7878718e94ad8b4132013f925e71f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 18:55:58 +0100 Subject: [PATCH 075/172] workbench - move restoreTimeoutHandle to a better place --- .../workbench/electron-browser/workbench.ts | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 0625ab7372a..bdeb9e52ede 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -189,7 +189,6 @@ export class Workbench extends Disposable implements IPartService { private editorGroupService: IEditorGroupsService; private contextViewService: ContextViewService; private windowService: IWindowService; - private lifecycleService: ILifecycleService; private instantiationService: IInstantiationService; private contextService: IWorkspaceContextService; @@ -342,10 +341,6 @@ export class Workbench extends Disposable implements IPartService { // Layout this.layout(); - // Handle case where workbench is not starting up properly - const timeoutHandle = setTimeout(() => this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.'), 10000); - this.lifecycleService.when(LifecyclePhase.Restored).then(() => clearTimeout(timeoutHandle)); - // Restore Parts let error: Error; return this.restoreParts() @@ -408,10 +403,10 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(ITelemetryService, telemetryService); // Lifecycle - this.lifecycleService = this.instantiationService.createInstance(LifecycleService); - serviceCollection.set(ILifecycleService, this.lifecycleService); - this._register(this.lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event))); - this._register(this.lifecycleService.onShutdown(() => { + const lifecycleService = this.instantiationService.createInstance(LifecycleService); + serviceCollection.set(ILifecycleService, lifecycleService); + this._register(lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event))); + this._register(lifecycleService.onShutdown(() => { this._onShutdown.fire(); this.dispose(); })); @@ -726,7 +721,7 @@ export class Workbench extends Disposable implements IPartService { registerNotificationCommands(this.notificationsCenter, this.notificationsToasts); } - private restoreParts(): Promise { + private restoreParts(): Promise { const restorePromises: Promise[] = []; // Restore editors @@ -779,7 +774,10 @@ export class Workbench extends Disposable implements IPartService { this.centerEditorLayout(true); } - return Promise.all(restorePromises); + // Emit a warning after 10s if restore does not complete + const restoreTimeoutHandle = setTimeout(() => this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.'), 10000); + + return Promise.all(restorePromises).then(() => clearTimeout(restoreTimeoutHandle)); } private whenStarted(accessor: ServicesAccessor, error?: Error): void { From 2f4ee72b2ac4c93640f04d07c12801d20e19fc88 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Mar 2019 18:58:50 +0100 Subject: [PATCH 076/172] :lipstick: --- src/vs/workbench/electron-browser/workbench.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index bdeb9e52ede..39de9310f86 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -341,11 +341,8 @@ export class Workbench extends Disposable implements IPartService { // Layout this.layout(); - // Restore Parts - let error: Error; - return this.restoreParts() - .catch(err => error = err) - .finally(() => this.instantiationService.invokeFunction(accessor => this.whenStarted(accessor, error))); + // Restore + return this.restoreWorkbench(); } private createWorkbenchContainer(): void { @@ -721,7 +718,7 @@ export class Workbench extends Disposable implements IPartService { registerNotificationCommands(this.notificationsCenter, this.notificationsToasts); } - private restoreParts(): Promise { + private restoreWorkbench(): Promise { const restorePromises: Promise[] = []; // Restore editors @@ -777,10 +774,15 @@ export class Workbench extends Disposable implements IPartService { // Emit a warning after 10s if restore does not complete const restoreTimeoutHandle = setTimeout(() => this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.'), 10000); - return Promise.all(restorePromises).then(() => clearTimeout(restoreTimeoutHandle)); + let error: Error; + return Promise.all(restorePromises) + .then(() => clearTimeout(restoreTimeoutHandle)) + .catch(err => error = err) + .finally(() => this.instantiationService.invokeFunction(accessor => this.whenRestored(accessor, error))); + } - private whenStarted(accessor: ServicesAccessor, error?: Error): void { + private whenRestored(accessor: ServicesAccessor, error?: Error): void { const lifecycleService = accessor.get(ILifecycleService); this.restored = true; From d52d4bb0fa3e7081b21e48a4e1c770af96efd3f8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 11:55:15 -0800 Subject: [PATCH 077/172] Strict null check untitledEditor --- src/tsconfig.strictNullChecks.json | 13 +++++++++++-- src/vs/base/common/mime.ts | 2 +- .../workbench/common/editor/untitledEditorInput.ts | 2 +- .../workbench/common/editor/untitledEditorModel.ts | 6 +++--- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 9bdb62faf4d..2a44a480baf 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -98,6 +98,7 @@ "./vs/workbench/browser/composite.ts", "./vs/workbench/browser/contextkeys.ts", "./vs/workbench/browser/editor.ts", + "./vs/workbench/browser/labels.ts", "./vs/workbench/browser/panel.ts", "./vs/workbench/browser/part.ts", "./vs/workbench/browser/parts/compositePart.ts", @@ -114,6 +115,7 @@ "./vs/workbench/browser/parts/editor/resourceViewer.ts", "./vs/workbench/browser/parts/editor/sideBySideEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", + "./vs/workbench/browser/parts/editor/textResourceEditor.ts", "./vs/workbench/browser/parts/quickinput/quickInputBox.ts", "./vs/workbench/browser/parts/quickinput/quickInputList.ts", "./vs/workbench/browser/parts/quickinput/quickInputUtils.ts", @@ -145,6 +147,8 @@ "./vs/workbench/common/editor/resourceEditorModel.ts", "./vs/workbench/common/editor/textDiffEditorModel.ts", "./vs/workbench/common/editor/textEditorModel.ts", + "./vs/workbench/common/editor/untitledEditorInput.ts", + "./vs/workbench/common/editor/untitledEditorModel.ts", "./vs/workbench/common/memento.ts", "./vs/workbench/common/notifications.ts", "./vs/workbench/common/panel.ts", @@ -206,11 +210,11 @@ "./vs/workbench/contrib/extensions/common/extensions.ts", "./vs/workbench/contrib/extensions/common/extensionsFileTemplate.ts", "./vs/workbench/contrib/extensions/common/extensionsInput.ts", + "./vs/workbench/contrib/extensions/common/extensionsUtils.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActivationProgress.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsList.ts", - "./vs/workbench/contrib/extensions/common/extensionsUtils.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsWidgets.ts", "./vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput.ts", "./vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts", @@ -221,6 +225,7 @@ "./vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts", "./vs/workbench/contrib/files/browser/files.ts", "./vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts", + "./vs/workbench/contrib/files/common/dirtyFilesTracker.ts", "./vs/workbench/contrib/files/common/editors/fileEditorInput.ts", "./vs/workbench/contrib/files/common/explorerModel.ts", "./vs/workbench/contrib/files/common/explorerService.ts", @@ -240,6 +245,9 @@ "./vs/workbench/contrib/markers/browser/markersPanelActions.ts", "./vs/workbench/contrib/markers/browser/messages.ts", "./vs/workbench/contrib/markers/test/electron-browser/markersModel.test.ts", + "./vs/workbench/contrib/output/browser/logViewer.ts", + "./vs/workbench/contrib/output/browser/outputActions.ts", + "./vs/workbench/contrib/output/browser/outputPanel.ts", "./vs/workbench/contrib/output/common/output.ts", "./vs/workbench/contrib/output/common/outputLinkComputer.ts", "./vs/workbench/contrib/output/common/outputLinkProvider.ts", @@ -340,9 +348,9 @@ "./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts", "./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts", "./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts", + "./vs/workbench/services/extensions/node/extensionHostProtocol.ts", "./vs/workbench/services/extensions/node/extensionManagementServerService.ts", "./vs/workbench/services/extensions/node/extensionPoints.ts", - "./vs/workbench/services/extensions/node/extensionHostProtocol.ts", "./vs/workbench/services/extensions/node/lazyPromise.ts", "./vs/workbench/services/extensions/node/proxyIdentifier.ts", "./vs/workbench/services/extensions/node/rpcProtocol.ts", @@ -410,6 +418,7 @@ "./vs/workbench/services/textfile/common/textfiles.ts", "./vs/workbench/services/textfile/node/textResourcePropertiesService.ts", "./vs/workbench/services/title/common/titleService.ts", + "./vs/workbench/services/untitled/common/untitledEditorService.ts", "./vs/workbench/services/viewlet/browser/viewlet.ts", "./vs/workbench/services/workspace/common/workspaceEditing.ts", "./vs/workbench/test/browser/actionRegistry.test.ts", diff --git a/src/vs/base/common/mime.ts b/src/vs/base/common/mime.ts index 10ab55362b1..de19c7c03f8 100644 --- a/src/vs/base/common/mime.ts +++ b/src/vs/base/common/mime.ts @@ -230,7 +230,7 @@ export function isUnspecific(mime: string[] | string): boolean { * 2. Otherwise, if there are other extensions, suggest the first one. * 3. Otherwise, suggest the prefix. */ -export function suggestFilename(langId: string, prefix: string): string { +export function suggestFilename(langId: string | null, prefix: string): string { const extensions = registeredAssociations .filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === langId) .map(assoc => assoc.extension); diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index a4fe328d79d..9d3ebed0a01 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -63,7 +63,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport return this.resource; } - getModeId(): string { + getModeId(): string | null { if (this.cachedModel) { return this.cachedModel.getModeId(); } diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 4d14923cc3f..a19c5e64cf2 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -90,7 +90,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin return this.versionId; } - getModeId(): string { + getModeId(): string | null { if (this.textEditorModel) { return this.textEditorModel.getLanguageIdentifier().language; } @@ -139,7 +139,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin load(): Promise { // Check for backups first - return this.backupFileService.loadBackupResource(this.resource).then(backupResource => { + return this.backupFileService.loadBackupResource(this.resource).then((backupResource) => { if (backupResource) { return this.backupFileService.resolveBackupContent(backupResource); } @@ -193,7 +193,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin // mark the untitled editor as non-dirty once its content becomes empty and we do // not have an associated path set. we never want dirty indicator in that case. - if (!this._hasAssociatedFilePath && this.textEditorModel.getLineCount() === 1 && this.textEditorModel.getLineContent(1) === '') { + if (!this._hasAssociatedFilePath && this.textEditorModel && this.textEditorModel.getLineCount() === 1 && this.textEditorModel.getLineContent(1) === '') { this.setDirty(false); } From 314564c5910575ca44131911c1dd3ad8a3c0e39e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 12:00:17 -0800 Subject: [PATCH 078/172] Strict null check diffEditorModel --- src/tsconfig.strictNullChecks.json | 2 ++ .../common/editor/diffEditorModel.ts | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 2a44a480baf..306f8343f65 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -141,6 +141,7 @@ "./vs/workbench/common/editor.ts", "./vs/workbench/common/editor/binaryEditorModel.ts", "./vs/workbench/common/editor/dataUriEditorInput.ts", + "./vs/workbench/common/editor/diffEditorInput.ts", "./vs/workbench/common/editor/diffEditorModel.ts", "./vs/workbench/common/editor/editorGroup.ts", "./vs/workbench/common/editor/resourceEditorInput.ts", @@ -251,6 +252,7 @@ "./vs/workbench/contrib/output/common/output.ts", "./vs/workbench/contrib/output/common/outputLinkComputer.ts", "./vs/workbench/contrib/output/common/outputLinkProvider.ts", + "./vs/workbench/contrib/output/electron-browser/outputServices.ts", "./vs/workbench/contrib/output/node/outputAppender.ts", "./vs/workbench/contrib/preferences/browser/settingsWidgets.ts", "./vs/workbench/contrib/preferences/common/smartSnippetInserter.ts", diff --git a/src/vs/workbench/common/editor/diffEditorModel.ts b/src/vs/workbench/common/editor/diffEditorModel.ts index 794afd369d5..8405f386269 100644 --- a/src/vs/workbench/common/editor/diffEditorModel.ts +++ b/src/vs/workbench/common/editor/diffEditorModel.ts @@ -11,33 +11,39 @@ import { IEditorModel } from 'vs/platform/editor/common/editor'; * and the modified version. */ export class DiffEditorModel extends EditorModel { - protected _originalModel: IEditorModel; - protected _modifiedModel: IEditorModel; + protected _originalModel: IEditorModel | null; + protected _modifiedModel: IEditorModel | null; - constructor(originalModel: IEditorModel, modifiedModel: IEditorModel) { + constructor(originalModel: IEditorModel | null, modifiedModel: IEditorModel | null) { super(); this._originalModel = originalModel; this._modifiedModel = modifiedModel; } - get originalModel(): EditorModel { + get originalModel(): EditorModel | null { + if (!this._originalModel) { + return null; + } return this._originalModel as EditorModel; } - get modifiedModel(): EditorModel { + get modifiedModel(): EditorModel | null { + if (!this._modifiedModel) { + return null; + } return this._modifiedModel as EditorModel; } load(): Promise { return Promise.all([ - this._originalModel.load(), - this._modifiedModel.load() + this._originalModel ? this._originalModel.load() : Promise.resolve(undefined), + this._modifiedModel ? this._modifiedModel.load() : Promise.resolve(undefined), ]).then(() => this); } isResolved(): boolean { - return this.originalModel.isResolved() && this.modifiedModel.isResolved(); + return !!this.originalModel && this.originalModel.isResolved() && !!this.modifiedModel && this.modifiedModel.isResolved(); } dispose(): void { From 873b17fce6325123258270dd50d0fec190c6f8b4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 13:29:19 -0800 Subject: [PATCH 079/172] Strict null check dnd --- src/tsconfig.strictNullChecks.json | 4 ++++ src/vs/workbench/browser/dnd.ts | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 306f8343f65..e9512508680 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -97,10 +97,12 @@ "./vs/workbench/browser/actions/workspaceCommands.ts", "./vs/workbench/browser/composite.ts", "./vs/workbench/browser/contextkeys.ts", + "./vs/workbench/browser/dnd.ts", "./vs/workbench/browser/editor.ts", "./vs/workbench/browser/labels.ts", "./vs/workbench/browser/panel.ts", "./vs/workbench/browser/part.ts", + "./vs/workbench/browser/parts/compositeBarActions.ts", "./vs/workbench/browser/parts/compositePart.ts", "./vs/workbench/browser/parts/editor/baseEditor.ts", "./vs/workbench/browser/parts/editor/binaryDiffEditor.ts", @@ -225,6 +227,7 @@ "./vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts", "./vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts", "./vs/workbench/contrib/files/browser/files.ts", + "./vs/workbench/contrib/files/browser/views/emptyView.ts", "./vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts", "./vs/workbench/contrib/files/common/dirtyFilesTracker.ts", "./vs/workbench/contrib/files/common/editors/fileEditorInput.ts", @@ -252,6 +255,7 @@ "./vs/workbench/contrib/output/common/output.ts", "./vs/workbench/contrib/output/common/outputLinkComputer.ts", "./vs/workbench/contrib/output/common/outputLinkProvider.ts", + "./vs/workbench/contrib/output/electron-browser/output.contribution.ts", "./vs/workbench/contrib/output/electron-browser/outputServices.ts", "./vs/workbench/contrib/output/node/outputAppender.ts", "./vs/workbench/contrib/preferences/browser/settingsWidgets.ts", diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 9b036521f2e..41feee3ebe4 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -162,7 +162,7 @@ export class ResourcesDropHandler { ) { } - handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup | undefined, afterDrop: (targetGroup: IEditorGroup) => void, targetIndex?: number): void { + handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup | undefined, afterDrop: (targetGroup: IEditorGroup | undefined) => void, targetIndex?: number): void { const untitledOrFileResources = extractResources(event).filter(r => this.fileService.canHandleResource(r.resource) || r.resource.scheme === Schemas.untitled); if (!untitledOrFileResources.length) { return; @@ -235,10 +235,10 @@ export class ResourcesDropHandler { } // Resolve the contents of the dropped dirty resource from source - return this.backupFileService.resolveBackupContent(droppedDirtyEditor.backupResource).then(content => { + return this.backupFileService.resolveBackupContent(droppedDirtyEditor.backupResource!).then(content => { // Set the contents of to the resource to the target - return this.backupFileService.backupResource(droppedDirtyEditor.resource, content.create(this.getDefaultEOL()).createSnapshot(true)); + return this.backupFileService.backupResource(droppedDirtyEditor.resource, content!.create(this.getDefaultEOL()).createSnapshot(true)); }).then(() => false, () => false /* ignore any error */); } From a6dee4c4070ceb79b307c5c16d649908acf668e7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:18:49 -0800 Subject: [PATCH 080/172] Strict null check textDiffEditor --- src/tsconfig.strictNullChecks.json | 1 + src/vs/editor/common/editorCommon.ts | 2 +- .../browser/parts/editor/textDiffEditor.ts | 15 ++++++++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index e9512508680..45a5b9b1948 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -116,6 +116,7 @@ "./vs/workbench/browser/parts/editor/rangeDecorations.ts", "./vs/workbench/browser/parts/editor/resourceViewer.ts", "./vs/workbench/browser/parts/editor/sideBySideEditor.ts", + "./vs/workbench/browser/parts/editor/textDiffEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", "./vs/workbench/browser/parts/editor/textResourceEditor.ts", "./vs/workbench/browser/parts/quickinput/quickInputBox.ts", diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index e969ff60627..bde26ab9802 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -469,7 +469,7 @@ export interface IDiffEditor extends IEditor { /** * Type the getModel() of IEditor. */ - getModel(): IDiffEditorModel; + getModel(): IDiffEditorModel | null; /** * Get the `original` editor. diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index b91fc19dbe6..88f2deeeb0b 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -61,7 +61,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { return new EditorMemento(this.getId(), key, Object.create(null), limit, editorGroupService); // do not persist in storage as diff editors are never persisted } - getTitle(): string { + getTitle(): string | null { if (this.input) { return this.input.getName(); } @@ -120,6 +120,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { // Readonly flag diffEditor.updateOptions({ readOnly: resolvedDiffEditorModel.isReadonly() }); + return undefined; }, error => { // In case we tried to open a file and the response indicates that this is not a text file, fallback to binary diff. @@ -262,7 +263,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { return super.loadTextEditorViewState(resource) as IDiffEditorViewState; // overridden for text diff editor support } - private saveTextDiffEditorViewState(input: EditorInput): void { + private saveTextDiffEditorViewState(input: EditorInput | null): void { if (!(input instanceof DiffEditorInput)) { return; // only supported for diff editor inputs } @@ -288,11 +289,11 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { } } - protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState { + protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState | null { return this.retrieveTextDiffEditorViewState(resource); // overridden for text diff editor support } - private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState { + private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState | null { const control = this.getControl(); const model = control.getModel(); if (!model || !model.modified || !model.original) { @@ -311,9 +312,9 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor { return control.saveViewState(); } - private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI { - let original: URI; - let modified: URI; + private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI | null { + let original: URI | null; + let modified: URI | null; if (modelOrInput instanceof DiffEditorInput) { original = modelOrInput.originalInput.getResource(); From def06bab4840aa766c959afb415b9af6930b4f5b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:24:22 -0800 Subject: [PATCH 081/172] Strict null check customView --- src/tsconfig.strictNullChecks.json | 2 ++ .../browser/parts/views/customView.ts | 18 +++++++++--------- src/vs/workbench/common/views.ts | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 45a5b9b1948..1248c348f7b 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -37,6 +37,7 @@ "./vs/nls.mock.ts", "./vs/vscode.d.ts", "./vs/vscode.proposed.d.ts", + "./vs/workbench/api/browser/viewsExtensionPoint.ts", "./vs/workbench/api/common/configurationExtensionPoint.ts", "./vs/workbench/api/common/jsonValidationExtensionPoint.ts", "./vs/workbench/api/common/menusExtensionPoint.ts", @@ -128,6 +129,7 @@ "./vs/workbench/browser/parts/sidebar/sidebarPart.ts", "./vs/workbench/browser/parts/statusbar/statusbar.ts", "./vs/workbench/browser/parts/statusbar/statusbarPart.ts", + "./vs/workbench/browser/parts/views/customView.ts", "./vs/workbench/browser/parts/views/panelViewlet.ts", "./vs/workbench/browser/parts/views/views.ts", "./vs/workbench/browser/parts/views/viewsViewlet.ts", diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 6dfc083014d..4450da30eb0 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -190,7 +190,7 @@ export class CustomTreeView extends Disposable implements ITreeView { private menus: TitleMenus; private markdownRenderer: MarkdownRenderer; - private markdownResult: IMarkdownRenderResult; + private markdownResult: IMarkdownRenderResult | null; private readonly _onDidExpandItem: Emitter = this._register(new Emitter()); readonly onDidExpandItem: Event = this._onDidExpandItem.event; @@ -242,15 +242,15 @@ export class CustomTreeView extends Disposable implements ITreeView { this.create(); } - private _dataProvider: ITreeViewDataProvider; - get dataProvider(): ITreeViewDataProvider { + private _dataProvider: ITreeViewDataProvider | null; + get dataProvider(): ITreeViewDataProvider | null { return this._dataProvider; } - set dataProvider(dataProvider: ITreeViewDataProvider) { + set dataProvider(dataProvider: ITreeViewDataProvider | null) { if (dataProvider) { this._dataProvider = new class implements ITreeViewDataProvider { - getChildren(node?: ITreeItem): Promise { + getChildren(node: ITreeItem): Promise { if (node && node.children) { return Promise.resolve(node.children); } @@ -377,7 +377,7 @@ export class CustomTreeView extends Disposable implements ITreeView { } private createTree() { - const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : undefined; + const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : null; const menus = this._register(this.instantiationService.createInstance(TreeMenus, this.id)); this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this)); const dataSource = this.instantiationService.createInstance(TreeDataSource, this, (task: Promise) => this.progressService.withProgress({ location: this.viewContainer.id }, () => task)); @@ -461,7 +461,7 @@ export class CustomTreeView extends Disposable implements ITreeView { this.elementsToRefresh = []; } for (const element of elements) { - element.children = null; // reset children + element.children = undefined; // reset children } if (this.isVisible) { return this.doRefresh(elements); @@ -676,7 +676,7 @@ class TreeRenderer implements IRenderer { renderElement(tree: ITree, node: ITreeItem, templateId: string, templateData: ITreeExplorerTemplateData): void { const resource = node.resourceUri ? URI.revive(node.resourceUri) : null; - const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource) } : undefined; + const treeItemLabel: ITreeItemLabel | undefined = node.label ? node.label : resource ? { label: basename(resource) } : undefined; const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : undefined; const label = treeItemLabel ? treeItemLabel.label : undefined; const matches = treeItemLabel && treeItemLabel.highlights ? treeItemLabel.highlights.map(([start, end]) => ({ start, end })) : undefined; @@ -872,7 +872,7 @@ class TreeMenus extends Disposable implements IDisposable { return this.getActions(MenuId.ViewItemContext, { key: 'viewItem', value: element.contextValue }).secondary; } - private getActions(menuId: MenuId, context: { key: string, value: string }): { primary: IAction[]; secondary: IAction[]; } { + private getActions(menuId: MenuId, context: { key: string, value?: string }): { primary: IAction[]; secondary: IAction[]; } { const contextKeyService = this.contextKeyService.createScoped(); contextKeyService.createKey('view', this.id); contextKeyService.createKey(context.key, context.value); diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 2a16b9bd9f6..7d08589c1a7 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -378,7 +378,7 @@ export interface ITreeItem { handle: string; - parentHandle: string; + parentHandle: string | null; collapsibleState: TreeItemCollapsibleState; From 2f088e6d969e6811ee55c68114662fbe18d7aae8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:29:51 -0800 Subject: [PATCH 082/172] Strict null check fileEditorTracker --- src/tsconfig.strictNullChecks.json | 1 + .../contrib/files/browser/editors/fileEditorTracker.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 1248c348f7b..1bb8941d011 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -229,6 +229,7 @@ "./vs/workbench/contrib/feedback/electron-browser/feedback.ts", "./vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts", "./vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts", + "./vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts", "./vs/workbench/contrib/files/browser/files.ts", "./vs/workbench/contrib/files/browser/views/emptyView.ts", "./vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts", diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts index c281e9d0bfb..cb15ee33d26 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts @@ -110,7 +110,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut private onFileOperation(e: FileOperationEvent): void { // Handle moves specially when file is opened - if (e.operation === FileOperation.MOVE) { + if (e.operation === FileOperation.MOVE && e.target) { this.handleMovedFileInOpenedEditors(e.resource, e.target.resource); } @@ -300,8 +300,8 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut // // Note: we also consider the added event because it could be that a file was added // and updated right after. - distinct([...e.getUpdated(), ...e.getAdded()] - .map(u => this.textFileService.models.get(u.resource)) + distinct(coalesce([...e.getUpdated(), ...e.getAdded()] + .map(u => this.textFileService.models.get(u.resource))) .filter(model => model && !model.isDirty()), m => m.getResource().toString()) .forEach(model => this.queueModelLoad(model)); } From ee75807070082f2c7b48632cd200ef1b948d2fd8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:30:28 -0800 Subject: [PATCH 083/172] Strict null check activitybarActions --- src/tsconfig.strictNullChecks.json | 1 + src/vs/workbench/browser/parts/sidebar/sidebarPart.ts | 6 +++--- src/vs/workbench/services/viewlet/browser/viewlet.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 1bb8941d011..839937fa0d8 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -103,6 +103,7 @@ "./vs/workbench/browser/labels.ts", "./vs/workbench/browser/panel.ts", "./vs/workbench/browser/part.ts", + "./vs/workbench/browser/parts/activitybar/activitybarActions.ts", "./vs/workbench/browser/parts/compositeBarActions.ts", "./vs/workbench/browser/parts/compositePart.ts", "./vs/workbench/browser/parts/editor/baseEditor.ts", diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index d1d90205df5..f17cef29eb2 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -199,14 +199,14 @@ export class SidebarPart extends CompositePart implements ISerializable this.hideActiveComposite(); } - openViewlet(id: string, focus?: boolean): Promise { - if (this.getViewlet(id)) { + openViewlet(id: string | undefined, focus?: boolean): Promise { + if (typeof id === 'string' && this.getViewlet(id)) { return Promise.resolve(this.doOpenViewlet(id, focus)); } return this.extensionService.whenInstalledExtensionsRegistered() .then(() => { - if (this.getViewlet(id)) { + if (typeof id === 'string' && this.getViewlet(id)) { return this.doOpenViewlet(id, focus); } diff --git a/src/vs/workbench/services/viewlet/browser/viewlet.ts b/src/vs/workbench/services/viewlet/browser/viewlet.ts index b87357e7630..88410fceb95 100644 --- a/src/vs/workbench/services/viewlet/browser/viewlet.ts +++ b/src/vs/workbench/services/viewlet/browser/viewlet.ts @@ -22,7 +22,7 @@ export interface IViewletService { /** * Opens a viewlet with the given identifier and pass keyboard focus to it if specified. */ - openViewlet(id: string, focus?: boolean): Promise; + openViewlet(id: string | undefined, focus?: boolean): Promise; /** * Returns the current active viewlet or null if none. From 367b5fc7ecbb18198ec08cd0c3d388e13cd3b316 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:34:39 -0800 Subject: [PATCH 084/172] Strict null check editorDropTarget --- src/tsconfig.strictNullChecks.json | 1 + .../browser/parts/editor/editorDropTarget.ts | 28 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 839937fa0d8..6085a5e39b0 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -113,6 +113,7 @@ "./vs/workbench/browser/parts/editor/breadcrumbsModel.ts", "./vs/workbench/browser/parts/editor/editor.ts", "./vs/workbench/browser/parts/editor/editorControl.ts", + "./vs/workbench/browser/parts/editor/editorDropTarget.ts", "./vs/workbench/browser/parts/editor/editorPicker.ts", "./vs/workbench/browser/parts/editor/editorWidgets.ts", "./vs/workbench/browser/parts/editor/rangeDecorations.ts", diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 52272c0d2f4..464a494ba92 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -28,7 +28,7 @@ class DropOverlay extends Themable { private container: HTMLElement; private overlay: HTMLElement; - private currentDropOperation: IDropOperation; + private currentDropOperation?: IDropOperation; private _disposed: boolean; private cleanupOverlayScheduler: RunOnceScheduler; @@ -103,12 +103,12 @@ class DropOverlay extends Themable { // 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 (!isDraggingEditor && !isDraggingGroup) { + if (!isDraggingEditor && !isDraggingGroup && e.dataTransfer) { e.dataTransfer.dropEffect = 'copy'; } // Find out if operation is valid - const isCopy = isDraggingGroup ? this.isCopyOperation(e) : isDraggingEditor ? this.isCopyOperation(e, this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier) : true; + const isCopy = isDraggingGroup ? this.isCopyOperation(e) : isDraggingEditor ? this.isCopyOperation(e, this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier) : true; if (!isCopy) { const sourceGroupView = this.findSourceGroupView(); if (sourceGroupView === this.groupView) { @@ -158,16 +158,16 @@ class DropOverlay extends Themable { })); } - private findSourceGroupView(): IEditorGroupView { + private findSourceGroupView(): IEditorGroupView | undefined { // Check for group transfer if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - return this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier); + return this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![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); + return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier.groupId); } return undefined; @@ -189,7 +189,7 @@ class DropOverlay extends Themable { // Check for group transfer if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const draggedEditorGroup = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier; + const draggedEditorGroup = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier; // Return if the drop is a no-op const sourceGroup = this.accessor.getGroup(draggedEditorGroup); @@ -222,7 +222,7 @@ class DropOverlay extends Themable { // Check for editor transfer else if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; const targetGroup = ensureTargetGroup(); // Return if the drop is a no-op @@ -250,7 +250,7 @@ class DropOverlay extends Themable { // Check for URI transfer else { const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ }); - dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => targetGroup.focus()); + dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => targetGroup!.focus()); } } @@ -298,7 +298,7 @@ class DropOverlay extends Themable { // child.style.top = edgeHeightThreshold + 'px'; // No split if mouse is above certain threshold in the center of the view - let splitDirection: GroupDirection; + let splitDirection: GroupDirection | undefined; if ( mousePosX > edgeWidthThreshold && mousePosX < editorControlWidth - edgeWidthThreshold && mousePosY > edgeHeightThreshold && mousePosY < editorControlHeight - edgeHeightThreshold @@ -429,7 +429,7 @@ class DropOverlay extends Themable { export class EditorDropTarget extends Themable { - private _overlay: DropOverlay; + private _overlay?: DropOverlay; private counter = 0; @@ -447,7 +447,7 @@ export class EditorDropTarget extends Themable { this.registerListeners(); } - private get overlay(): DropOverlay { + private get overlay(): DropOverlay | undefined { if (this._overlay && !this._overlay.disposed) { return this._overlay; } @@ -468,7 +468,7 @@ export class EditorDropTarget extends Themable { if ( !this.editorTransfer.hasData(DraggedEditorIdentifier.prototype) && !this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype) && - !event.dataTransfer.types.length // see https://github.com/Microsoft/vscode/issues/25789 + event.dataTransfer && !event.dataTransfer.types.length // see https://github.com/Microsoft/vscode/issues/25789 ) { event.dataTransfer.dropEffect = 'none'; return; // unsupported transfer @@ -510,7 +510,7 @@ export class EditorDropTarget extends Themable { this.disposeOverlay(); } - private findTargetGroupView(child: HTMLElement): IEditorGroupView { + private findTargetGroupView(child: HTMLElement): IEditorGroupView | undefined { const groups = this.accessor.groups; for (const groupView of groups) { if (isAncestor(child, groupView.element)) { From 7e05804a90d84ee5e27547b8938e0f9fb0ab525d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:40:44 -0800 Subject: [PATCH 085/172] Strict null check compositeBar --- src/tsconfig.strictNullChecks.json | 1 + .../workbench/browser/parts/compositeBar.ts | 34 +++++++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 6085a5e39b0..e261c8b964a 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -104,6 +104,7 @@ "./vs/workbench/browser/panel.ts", "./vs/workbench/browser/part.ts", "./vs/workbench/browser/parts/activitybar/activitybarActions.ts", + "./vs/workbench/browser/parts/compositeBar.ts", "./vs/workbench/browser/parts/compositeBarActions.ts", "./vs/workbench/browser/parts/compositePart.ts", "./vs/workbench/browser/parts/editor/baseEditor.ts", diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 4869bb20391..fe068d5c5c8 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -25,7 +25,7 @@ export interface ICompositeBarItem { id: string; name: string; pinned: boolean; - order: number; + order?: number; visible: boolean; } @@ -49,8 +49,8 @@ export class CompositeBar extends Widget implements ICompositeBar { private dimension: Dimension; private compositeSwitcherBar: ActionBar; - private compositeOverflowAction: CompositeOverflowActivityAction; - private compositeOverflowActionItem: CompositeOverflowActivityActionItem; + private compositeOverflowAction: CompositeOverflowActivityAction | null; + private compositeOverflowActionItem: CompositeOverflowActivityActionItem | null; private model: CompositeBarModel; private visibleComposites: string[]; @@ -174,7 +174,7 @@ export class CompositeBar extends Widget implements ICompositeBar { if (this.model.activate(id)) { // Update if current composite is neither visible nor pinned // or previous active composite is not pinned - if (this.visibleComposites.indexOf(id) === - 1 || !this.model.activeItem.pinned || (previousActiveItem && !previousActiveItem.pinned)) { + if (this.visibleComposites.indexOf(id) === - 1 || (!!this.model.activeItem && !this.model.activeItem.pinned) || (previousActiveItem && !previousActiveItem.pinned)) { this.updateCompositeSwitcher(); } } @@ -304,7 +304,7 @@ export class CompositeBar extends Widget implements ICompositeBar { let size = 0; const limit = this.options.orientation === ActionsOrientation.VERTICAL ? this.dimension.height : this.dimension.width; for (let i = 0; i < compositesToShow.length && size <= limit; i++) { - size += this.compositeSizeInBar.get(compositesToShow[i]); + size += this.compositeSizeInBar.get(compositesToShow[i])!; if (size > limit) { maxVisible = i; } @@ -312,19 +312,19 @@ export class CompositeBar extends Widget implements ICompositeBar { overflows = compositesToShow.length > maxVisible; if (overflows) { - size -= this.compositeSizeInBar.get(compositesToShow[maxVisible]); + size -= this.compositeSizeInBar.get(compositesToShow[maxVisible])!; compositesToShow = compositesToShow.slice(0, maxVisible); size += this.options.overflowActionSize; } // Check if we need to make extra room for the overflow action if (size > limit) { - size -= this.compositeSizeInBar.get(compositesToShow.pop()); + size -= this.compositeSizeInBar.get(compositesToShow.pop()!)!; } // We always try show the active composite - if (this.model.activeItem && compositesToShow.every(compositeId => compositeId !== this.model.activeItem.id)) { - const removedComposite = compositesToShow.pop(); - size = size - this.compositeSizeInBar.get(removedComposite) + this.compositeSizeInBar.get(this.model.activeItem.id); + if (this.model.activeItem && compositesToShow.every(compositeId => !!this.model.activeItem && compositeId !== this.model.activeItem.id)) { + const removedComposite = compositesToShow.pop()!; + size = size - this.compositeSizeInBar.get(removedComposite)! + this.compositeSizeInBar.get(this.model.activeItem.id)!; compositesToShow.push(this.model.activeItem.id); } @@ -342,7 +342,9 @@ export class CompositeBar extends Widget implements ICompositeBar { this.compositeOverflowAction.dispose(); this.compositeOverflowAction = null; - this.compositeOverflowActionItem.dispose(); + if (this.compositeOverflowActionItem) { + this.compositeOverflowActionItem.dispose(); + } this.compositeOverflowActionItem = null; } @@ -378,7 +380,11 @@ export class CompositeBar extends Widget implements ICompositeBar { // Add overflow action as needed if ((visibleCompositesChange && overflows) || this.compositeSwitcherBar.length() === 0) { - this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => this.compositeOverflowActionItem.showMenu()); + this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => { + if (this.compositeOverflowActionItem) { + this.compositeOverflowActionItem.showMenu(); + } + }); this.compositeOverflowActionItem = this.instantiationService.createInstance( CompositeOverflowActivityActionItem, this.compositeOverflowAction, @@ -453,7 +459,7 @@ class CompositeBarModel { private _items: ICompositeBarModelItem[]; private readonly options: ICompositeBarOptions; - activeItem: ICompositeBarModelItem; + activeItem?: ICompositeBarModelItem; constructor( items: ICompositeBarItem[], @@ -541,7 +547,7 @@ class CompositeBarModel { this.items.push(item); } else { let index = 0; - while (index < this.items.length && this.items[index].order < order) { + while (index < this.items.length && typeof this.items[index].order === 'number' && this.items[index].order! < order) { index++; } this.items.splice(index, 0, item); From 84c059ab525bbc99cb36c00afa8483758475c6f2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 14:54:51 -0800 Subject: [PATCH 086/172] Strict null check editorActions and editorCommands --- src/tsconfig.strictNullChecks.json | 2 ++ .../keybinding/common/keybindingsRegistry.ts | 2 +- .../browser/parts/editor/editorActions.ts | 8 +++---- .../browser/parts/editor/editorCommands.ts | 22 +++++++++---------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index e261c8b964a..e5f464ef6f3 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -113,6 +113,8 @@ "./vs/workbench/browser/parts/editor/breadcrumbs.ts", "./vs/workbench/browser/parts/editor/breadcrumbsModel.ts", "./vs/workbench/browser/parts/editor/editor.ts", + "./vs/workbench/browser/parts/editor/editorActions.ts", + "./vs/workbench/browser/parts/editor/editorCommands.ts", "./vs/workbench/browser/parts/editor/editorControl.ts", "./vs/workbench/browser/parts/editor/editorDropTarget.ts", "./vs/workbench/browser/parts/editor/editorPicker.ts", diff --git a/src/vs/platform/keybinding/common/keybindingsRegistry.ts b/src/vs/platform/keybinding/common/keybindingsRegistry.ts index bfa00350ebd..145508abb2a 100644 --- a/src/vs/platform/keybinding/common/keybindingsRegistry.ts +++ b/src/vs/platform/keybinding/common/keybindingsRegistry.ts @@ -19,7 +19,7 @@ export interface IKeybindingItem { } export interface IKeybindings { - primary: number; + primary?: number; secondary?: number[]; win?: { primary: number; diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 05ed83a7bca..205fdcaac49 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -952,7 +952,7 @@ export class OpenNextEditor extends BaseNavigateEditorAction { // Navigate in active group if possible const activeGroup = this.editorGroupService.activeGroup; const activeGroupEditors = activeGroup.getEditors(EditorsOrder.SEQUENTIAL); - const activeEditorIndex = activeGroupEditors.indexOf(activeGroup.activeEditor); + const activeEditorIndex = activeGroup.activeEditor ? activeGroupEditors.indexOf(activeGroup.activeEditor) : -1; if (activeEditorIndex + 1 < activeGroupEditors.length) { return { editor: activeGroupEditors[activeEditorIndex + 1], groupId: activeGroup.id }; } @@ -987,7 +987,7 @@ export class OpenPreviousEditor extends BaseNavigateEditorAction { // Navigate in active group if possible const activeGroup = this.editorGroupService.activeGroup; const activeGroupEditors = activeGroup.getEditors(EditorsOrder.SEQUENTIAL); - const activeEditorIndex = activeGroupEditors.indexOf(activeGroup.activeEditor); + const activeEditorIndex = activeGroup.activeEditor ? activeGroupEditors.indexOf(activeGroup.activeEditor) : -1; if (activeEditorIndex > 0) { return { editor: activeGroupEditors[activeEditorIndex - 1], groupId: activeGroup.id }; } @@ -1020,7 +1020,7 @@ export class OpenNextEditorInGroup extends BaseNavigateEditorAction { protected navigate(): IEditorIdentifier { const group = this.editorGroupService.activeGroup; const editors = group.getEditors(EditorsOrder.SEQUENTIAL); - const index = editors.indexOf(group.activeEditor); + const index = group.activeEditor ? editors.indexOf(group.activeEditor) : -1; return { editor: index + 1 < editors.length ? editors[index + 1] : editors[0], groupId: group.id }; } @@ -1043,7 +1043,7 @@ export class OpenPreviousEditorInGroup extends BaseNavigateEditorAction { protected navigate(): IEditorIdentifier { const group = this.editorGroupService.activeGroup; const editors = group.getEditors(EditorsOrder.SEQUENTIAL); - const index = editors.indexOf(group.activeEditor); + const index = group.activeEditor ? editors.indexOf(group.activeEditor) : -1; return { editor: index > 0 ? editors[index - 1] : editors[editors.length - 1], groupId: group.id }; } diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 25e420329d5..e1e12fc7790 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -16,7 +16,7 @@ import { URI } from 'vs/base/common/uri'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IListService } from 'vs/platform/list/browser/listService'; import { List } from 'vs/base/browser/ui/list/listWidget'; -import { distinct } from 'vs/base/common/arrays'; +import { distinct, coalesce } from 'vs/base/common/arrays'; import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredSideBySideGroupDirection, EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @@ -52,9 +52,9 @@ export const NAVIGATE_IN_ACTIVE_GROUP_PREFIX = 'edt active '; export const OPEN_EDITOR_AT_INDEX_COMMAND_ID = 'workbench.action.openEditorAtIndex'; export interface ActiveEditorMoveArguments { - to?: 'first' | 'last' | 'left' | 'right' | 'up' | 'down' | 'center' | 'position' | 'previous' | 'next'; - by?: 'tab' | 'group'; - value?: number; + to: 'first' | 'last' | 'left' | 'right' | 'up' | 'down' | 'center' | 'position' | 'previous' | 'next'; + by: 'tab' | 'group'; + value: number; } const isActiveEditorMoveArg = function (arg: ActiveEditorMoveArguments): boolean { @@ -357,7 +357,7 @@ function registerOpenEditorAtIndexCommands(): void { case 9: return KeyCode.KEY_9; } - return undefined; + throw new Error('invalid index'); } } @@ -409,7 +409,7 @@ function registerFocusEditorGroupAtIndexCommands(): void { case 7: return 'workbench.action.focusEighthEditorGroup'; } - return undefined; + throw new Error('Invalid index'); } function toKeyCode(index: number): KeyCode { @@ -423,7 +423,7 @@ function registerFocusEditorGroupAtIndexCommands(): void { case 7: return KeyCode.KEY_8; } - return undefined; + throw new Error('Invalid index'); } } @@ -528,9 +528,9 @@ function registerCloseEditorCommands() { return Promise.all(groupIds.map(groupId => { const group = editorGroupService.getGroup(groupId); - const editors = contexts + const editors = coalesce(contexts .filter(context => context.groupId === groupId) - .map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor); + .map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor)); return group.closeEditors(editors); })); @@ -675,7 +675,7 @@ function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, con return undefined; } -function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor: IEditorInput, control: IEditor } { +function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor?: IEditorInput, control?: IEditor } { // Resolve from context let group = context && typeof context.groupId === 'number' ? editorGroupService.getGroup(context.groupId) : undefined; @@ -689,7 +689,7 @@ function resolveCommandsContext(editorGroupService: IEditorGroupsService, contex control = group.activeControl; } - return { group, editor, control }; + return { group, editor: editor || undefined, control: control || undefined }; } export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsContext | undefined, listService: IListService, editorGroupService: IEditorGroupsService): IEditorCommandsContext[] { From aa912c88ede9b97f59cf36fe47fbc22ec0a206fc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:02:57 -0800 Subject: [PATCH 087/172] Strict null check activityBar --- src/tsconfig.strictNullChecks.json | 1 + .../parts/activitybar/activitybarPart.ts | 35 +++++++++++-------- .../workbench/browser/parts/compositeBar.ts | 6 ++-- .../browser/parts/compositeBarActions.ts | 16 ++++----- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index e5f464ef6f3..d0df318c885 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -104,6 +104,7 @@ "./vs/workbench/browser/panel.ts", "./vs/workbench/browser/part.ts", "./vs/workbench/browser/parts/activitybar/activitybarActions.ts", + "./vs/workbench/browser/parts/activitybar/activitybarPart.ts", "./vs/workbench/browser/parts/compositeBar.ts", "./vs/workbench/browser/parts/compositeBarActions.ts", "./vs/workbench/browser/parts/compositePart.ts", diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index f54dadfb511..caf40047a5a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -38,11 +38,11 @@ const SCM_VIEWLET_ID = 'workbench.view.scm'; interface ICachedViewlet { id: string; - iconUrl: UriComponents; + iconUrl?: UriComponents; pinned: boolean; - order: number; + order?: number; visible: boolean; - views?: { when: string }[]; + views?: { when?: string }[]; } export class ActivitybarPart extends Part implements ISerializableView { @@ -161,14 +161,19 @@ export class ActivitybarPart extends Part implements ISerializableView { private onDidViewletOpen(viewlet: IViewlet): void { // Update the composite bar by adding - this.compositeBar.addComposite(this.viewletService.getViewlet(viewlet.getId())); + const foundViewlet = this.viewletService.getViewlet(viewlet.getId()); + if (foundViewlet) { + this.compositeBar.addComposite(foundViewlet); + } this.compositeBar.activateComposite(viewlet.getId()); const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId()); - const viewContainer = this.getViewContainer(viewletDescriptor.id); - if (viewContainer) { - const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer); - if (viewDescriptors && viewDescriptors.activeViewDescriptors.length === 0) { - this.removeComposite(viewletDescriptor.id, true); // Update the composite bar by hiding + if (viewletDescriptor) { + const viewContainer = this.getViewContainer(viewletDescriptor.id); + if (viewContainer) { + const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer); + if (viewDescriptors && viewDescriptors.activeViewDescriptors.length === 0) { + this.removeComposite(viewletDescriptor.id, true); // Update the composite bar by hiding + } } } } @@ -241,7 +246,7 @@ export class ActivitybarPart extends Part implements ISerializableView { badgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND), badgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND), dragAndDropBackground: theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND), - activeBackgroundColor: null, inactiveBackgroundColor: null, activeBorderBottomColor: null, + activeBackgroundColor: undefined, inactiveBackgroundColor: undefined, activeBorderBottomColor: undefined, }; } @@ -311,7 +316,7 @@ export class ActivitybarPart extends Part implements ISerializableView { private shouldBeHidden(viewletId: string, cachedViewlet: ICachedViewlet): boolean { return cachedViewlet && cachedViewlet.views && cachedViewlet.views.length - ? cachedViewlet.views.every(({ when }) => when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when))) + ? 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 */; } @@ -371,7 +376,7 @@ export class ActivitybarPart extends Part implements ISerializableView { } // Pass to super - const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2)); + const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2!)); this.dimension = sizes[1]; @@ -428,7 +433,7 @@ export class ActivitybarPart extends Part implements ISerializableView { const viewContainer = this.getViewContainer(compositeItem.id); const viewlet = allViewlets.filter(({ id }) => id === compositeItem.id)[0]; if (viewlet) { - const views: { when: string }[] = []; + const views: { when: string | undefined }[] = []; if (viewContainer) { const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer); if (viewDescriptors) { @@ -471,7 +476,7 @@ export class ActivitybarPart extends Part implements ISerializableView { return result; } - private _cachedViewletsValue: string; + private _cachedViewletsValue: string | null; private get cachedViewletsValue(): string { if (!this._cachedViewletsValue) { this._cachedViewletsValue = this.getStoredCachedViewletsValue(); @@ -498,7 +503,7 @@ export class ActivitybarPart extends Part implements ISerializableView { private getViewContainer(viewletId: string): ViewContainer | undefined { // TODO: @Joao Remove this after moving SCM Viewlet to ViewContainerViewlet - https://github.com/Microsoft/vscode/issues/49054 if (viewletId === SCM_VIEWLET_ID) { - return null; + return undefined; } const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index fe068d5c5c8..a1367bbb2e6 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -23,7 +23,7 @@ import { Emitter, Event } from 'vs/base/common/event'; export interface ICompositeBarItem { id: string; - name: string; + name?: string; pinned: boolean; order?: number; visible: boolean; @@ -404,7 +404,7 @@ export class CompositeBar extends Widget implements ICompositeBar { this._onDidChange.fire(); } - private getOverflowingComposites(): { id: string, name: string }[] { + private getOverflowingComposites(): { id: string, name?: string }[] { let overflowingIds = this.model.visibleItems.filter(item => item.pinned).map(item => item.id); // Show the active composite even if it is not pinned @@ -513,7 +513,7 @@ class CompositeBarModel { return this.items.filter(item => item.visible && item.pinned); } - private createCompositeBarItem(id: string, name: string, order: number | undefined, pinned: boolean, visible: boolean): ICompositeBarModelItem { + private createCompositeBarItem(id: string, name: string | undefined, order: number | undefined, pinned: boolean, visible: boolean): ICompositeBarModelItem { const options = this.options; return { id, name, pinned, order, visible, diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 6e59e616bcd..f6763258e5e 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -108,14 +108,14 @@ export class ActivityAction extends Action { } export interface ICompositeBarColors { - activeBackgroundColor: Color; - inactiveBackgroundColor: Color; - activeBorderBottomColor: Color; - activeForegroundColor: Color; - inactiveForegroundColor: Color; - badgeBackground: Color; - badgeForeground: Color; - dragAndDropBackground: Color; + activeBackgroundColor?: Color; + inactiveBackgroundColor?: Color; + activeBorderBottomColor?: Color; + activeForegroundColor?: Color; + inactiveForegroundColor?: Color; + badgeBackground?: Color; + badgeForeground?: Color; + dragAndDropBackground?: Color; } export interface IActivityActionItemOptions extends IBaseActionItemOptions { From b76fecb4138aefb0dc1a86f4fe403c3a19ffbd62 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:06:12 -0800 Subject: [PATCH 088/172] Strict null check listCommands --- src/tsconfig.strictNullChecks.json | 1 + src/vs/workbench/browser/actions/listCommands.ts | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index d0df318c885..98fe291b7b1 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -93,6 +93,7 @@ "./vs/workbench/api/shared/tasks.ts", "./vs/workbench/browser/actions.ts", "./vs/workbench/browser/actions/layoutActions.ts", + "./vs/workbench/browser/actions/listCommands.ts", "./vs/workbench/browser/actions/navigationActions.ts", "./vs/workbench/browser/actions/workspaceActions.ts", "./vs/workbench/browser/actions/workspaceCommands.ts", diff --git a/src/vs/workbench/browser/actions/listCommands.ts b/src/vs/workbench/browser/actions/listCommands.ts index e89ad255348..7afe64bfa83 100644 --- a/src/vs/workbench/browser/actions/listCommands.ts +++ b/src/vs/workbench/browser/actions/listCommands.ts @@ -88,10 +88,12 @@ function expandMultiSelection(focused: List | PagedList | ITree | Obje const focus = list.getFocus() ? list.getFocus()[0] : undefined; const selection = list.getSelection(); - if (selection && selection.indexOf(focus) >= 0) { + if (selection && typeof focus === 'number' && selection.indexOf(focus) >= 0) { list.setSelection(selection.filter(s => s !== previousFocus)); } else { - list.setSelection(selection.concat(focus)); + if (typeof focus === 'number') { + list.setSelection(selection.concat(focus)); + } } } @@ -636,7 +638,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ const selectedNode = tree.getNode(start); const parentNode = selectedNode.parent; - if (!parentNode.parent) { // root + if (!parentNode || !parentNode.parent) { // root scope = undefined; } else { scope = parentNode.element; From a588a963fa2809363dc42b4f6ae3f62e30f4fbbe Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:10:01 -0800 Subject: [PATCH 089/172] Strict null check panelActions --- src/tsconfig.strictNullChecks.json | 3 +++ src/vs/platform/actions/common/actions.ts | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 98fe291b7b1..46e3c38c1d5 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -127,6 +127,8 @@ "./vs/workbench/browser/parts/editor/textDiffEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", "./vs/workbench/browser/parts/editor/textResourceEditor.ts", + "./vs/workbench/browser/parts/panel/panelActions.ts", + "./vs/workbench/browser/parts/panel/panelPart.ts", "./vs/workbench/browser/parts/quickinput/quickInputBox.ts", "./vs/workbench/browser/parts/quickinput/quickInputList.ts", "./vs/workbench/browser/parts/quickinput/quickInputUtils.ts", @@ -337,6 +339,7 @@ "./vs/workbench/contrib/url/common/url.contribution.ts", "./vs/workbench/contrib/webview/electron-browser/webviewProtocols.ts", "./vs/workbench/electron-browser/window.ts", + "./vs/workbench/services/activity/browser/activityService.ts", "./vs/workbench/services/activity/common/activity.ts", "./vs/workbench/services/backup/common/backup.ts", "./vs/workbench/services/backup/node/backupFileService.ts", diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index e615685b30b..b3bc081c9c5 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -281,13 +281,13 @@ export class SyncActionDescriptor { private _descriptor: SyncDescriptor0; private _id: string; - private _label: string; + private _label?: string; private _keybindings: IKeybindings | undefined; private _keybindingContext: ContextKeyExpr | undefined; private _keybindingWeight: number | undefined; constructor(ctor: IConstructorSignature2, - id: string, label: string, keybindings?: IKeybindings, keybindingContext?: ContextKeyExpr, keybindingWeight?: number + id: string, label: string | undefined, keybindings?: IKeybindings, keybindingContext?: ContextKeyExpr, keybindingWeight?: number ) { this._id = id; this._label = label; @@ -305,7 +305,7 @@ export class SyncActionDescriptor { return this._id; } - public get label(): string { + public get label(): string | undefined { return this._label; } From 3183a7a0f04fdf269eef08633545054613763e46 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:35:36 -0800 Subject: [PATCH 090/172] Strict null check breadcrumbsControl --- src/tsconfig.strictNullChecks.json | 2 ++ .../parts/editor/breadcrumbsControl.ts | 31 ++++++++++++------- .../browser/parts/editor/breadcrumbsPicker.ts | 18 ++++++++--- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 46e3c38c1d5..408ec1a80a1 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -113,7 +113,9 @@ "./vs/workbench/browser/parts/editor/binaryDiffEditor.ts", "./vs/workbench/browser/parts/editor/binaryEditor.ts", "./vs/workbench/browser/parts/editor/breadcrumbs.ts", + "./vs/workbench/browser/parts/editor/breadcrumbsControl.ts", "./vs/workbench/browser/parts/editor/breadcrumbsModel.ts", + "./vs/workbench/browser/parts/editor/breadcrumbsPicker.ts", "./vs/workbench/browser/parts/editor/editor.ts", "./vs/workbench/browser/parts/editor/editorActions.ts", "./vs/workbench/browser/parts/editor/editorCommands.ts", diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 1b9aad2e2fb..84acd81c48f 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -451,13 +451,15 @@ export class BreadcrumbsControl { } else if (element instanceof OutlineElement) { // open symbol in code editor const model = OutlineModel.get(element); - this._codeEditorService.openCodeEditor({ - resource: model.textModel.uri, - options: { - selection: Range.collapseToStart(element.symbol.selectionRange), - revealInCenterIfOutsideViewport: true - } - }, this._getActiveCodeEditor() || null, group === SIDE_GROUP); + if (model) { + this._codeEditorService.openCodeEditor({ + resource: model.textModel.uri, + options: { + selection: Range.collapseToStart(element.symbol.selectionRange), + revealInCenterIfOutsideViewport: true + } + }, this._getActiveCodeEditor() || null, group === SIDE_GROUP); + } } } @@ -640,7 +642,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } widget.setFocused(undefined); widget.setSelection(undefined); - groups.activeGroup.activeControl.focus(); + if (groups.activeGroup.activeControl) { + groups.activeGroup.activeControl.focus(); + } } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ @@ -651,15 +655,20 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler(accessor) { const editors = accessor.get(IEditorService); const lists = accessor.get(IListService); - const element = lists.lastFocusedList.getFocus(); + const element = lists.lastFocusedList ? lists.lastFocusedList.getFocus() : undefined; if (element instanceof OutlineElement) { + const outlineElement = OutlineModel.get(element); + if (!outlineElement) { + return undefined; + } + // open symbol in editor return editors.openEditor({ - resource: OutlineModel.get(element).textModel.uri, + resource: outlineElement.textModel.uri, options: { selection: Range.collapseToStart(element.symbol.selectionRange) } }, SIDE_GROUP); - } else if (URI.isUri(element.resource)) { + } else if (element && URI.isUri(element.resource)) { // open file in editor return editors.openEditor({ resource: element.resource, diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts index b0d991ac9eb..ff004ddd94a 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts @@ -25,9 +25,10 @@ import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/wor 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 { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter, IDataSource } from 'vs/base/browser/ui/tree/tree'; import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineItem } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list'; +import { IDataTreeOptions } from 'vs/base/browser/ui/tree/dataTree'; export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker { const ctor: IConstructorSignature1 = element instanceof FileElement @@ -156,7 +157,7 @@ export abstract class BreadcrumbsPicker { protected abstract _setInput(element: BreadcrumbElement): Promise; protected abstract _createTree(container: HTMLElement): Tree; - protected abstract _getTargetFromEvent(element: any, payload: UIEvent): any | undefined; + protected abstract _getTargetFromEvent(element: any, payload: UIEvent | undefined): any | undefined; } //#region - Files @@ -329,7 +330,7 @@ class FileFilter implements ITreeFilter { return true; } - const expression = this._cachedExpressions.get(folder.uri.toString()); + const expression = this._cachedExpressions.get(folder.uri.toString())!; return !expression(element.resource.path, basename(element.resource)); } } @@ -450,7 +451,14 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { } protected _createTree(container: HTMLElement) { - return this._instantiationService.createInstance( + return this._instantiationService.createInstance< + HTMLElement, + IListVirtualDelegate, + ITreeRenderer[], + IDataSource, + IDataTreeOptions, + WorkbenchDataTree + >( WorkbenchDataTree, container, new OutlineVirtualDelegate(), @@ -474,7 +482,7 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker { protected _setInput(input: BreadcrumbElement): Promise { const element = input as TreeElement; - const model = OutlineModel.get(element); + const model = OutlineModel.get(element)!; const tree = this._tree as WorkbenchDataTree; tree.setInput(model); From 50d502af617d15872b281ec8a6207446917c5497 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:42:00 -0800 Subject: [PATCH 091/172] Strict null check title control --- src/tsconfig.strictNullChecks.json | 1 + .../browser/parts/editor/titleControl.ts | 17 +++++++++------- src/vs/workbench/common/resources.ts | 20 +++++++++---------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 408ec1a80a1..7eb6cc2e03d 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -129,6 +129,7 @@ "./vs/workbench/browser/parts/editor/textDiffEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", "./vs/workbench/browser/parts/editor/textResourceEditor.ts", + "./vs/workbench/browser/parts/editor/titleControl.ts", "./vs/workbench/browser/parts/panel/panelActions.ts", "./vs/workbench/browser/parts/panel/panelPart.ts", "./vs/workbench/browser/parts/quickinput/quickInputBox.ts", diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 0a2b6fb57c7..fb31f528691 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -264,12 +264,14 @@ export abstract class TitleControl extends Themable { } // Drag Image - let label = this.group.activeEditor.getName(); - if (this.accessor.partOptions.showTabs && this.group.count > 1) { - label = localize('draggedEditorGroup', "{0} (+{1})", label, this.group.count - 1); - } + if (this.group.activeEditor) { + let label = this.group.activeEditor.getName(); + if (this.accessor.partOptions.showTabs && this.group.count > 1) { + label = localize('draggedEditorGroup', "{0} (+{1})", label, this.group.count - 1); + } - applyDragImage(e, label, 'monaco-editor-group-drag-image'); + applyDragImage(e, label, 'monaco-editor-group-drag-image'); + } })); // Drag end @@ -304,7 +306,7 @@ export abstract class TitleControl extends Themable { onHide: () => { // restore previous context - this.resourceContext.set(currentContext); + this.resourceContext.set(currentContext || null); // restore focus to active group this.accessor.activeGroup.focus(); @@ -355,7 +357,8 @@ export abstract class TitleControl extends Themable { } dispose(): void { - this.breadcrumbsControl = dispose(this.breadcrumbsControl); + dispose(this.breadcrumbsControl); + this.breadcrumbsControl = undefined; this.editorToolBarMenuDisposables = dispose(this.editorToolBarMenuDisposables); super.dispose(); diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index b8cf29b7272..6a597a960ff 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -25,11 +25,11 @@ export class ResourceContextKey extends Disposable implements IContextKey { static HasResource = new RawContextKey('resourceSet', false); static IsFileSystemResource = new RawContextKey('isFileSystemResource', false); - private readonly _resourceKey: IContextKey; - private readonly _schemeKey: IContextKey; - private readonly _filenameKey: IContextKey; + private readonly _resourceKey: IContextKey; + private readonly _schemeKey: IContextKey; + private readonly _filenameKey: IContextKey; private readonly _langIdKey: IContextKey; - private readonly _extensionKey: IContextKey; + private readonly _extensionKey: IContextKey; private readonly _hasResource: IContextKey; private readonly _isFileSystemResource: IContextKey; @@ -59,15 +59,15 @@ export class ResourceContextKey extends Disposable implements IContextKey { })); } - set(value: URI) { + set(value: URI | null) { if (!ResourceContextKey._uriEquals(this._resourceKey.get(), value)) { this._resourceKey.set(value); - this._schemeKey.set(value && value.scheme); - this._filenameKey.set(value && basename(value)); + this._schemeKey.set(value ? value.scheme : null); + this._filenameKey.set(value ? basename(value) : null); this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value.fsPath) : null); - this._extensionKey.set(value && extname(value)); + this._extensionKey.set(value ? extname(value) : null); this._hasResource.set(!!value); - this._isFileSystemResource.set(value && this._fileService.canHandleResource(value)); + this._isFileSystemResource.set(value ? this._fileService.canHandleResource(value) : false); } } @@ -82,7 +82,7 @@ export class ResourceContextKey extends Disposable implements IContextKey { } get(): URI | undefined { - return this._resourceKey.get(); + return this._resourceKey.get() || undefined; } private static _uriEquals(a: URI | undefined | null, b: URI | undefined | null): boolean { From a5d63ae52e4f8cbfddba4dd8151d81834592e7ec Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:53:55 -0800 Subject: [PATCH 092/172] Strict null work on tabsTitleControl --- src/tsconfig.strictNullChecks.json | 2 + .../parts/editor/noTabsTitleControl.ts | 26 +++++--- .../browser/parts/editor/tabsTitleControl.ts | 61 ++++++++++++------- src/vs/workbench/common/editor.ts | 2 +- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 7eb6cc2e03d..835e5e859a2 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -123,9 +123,11 @@ "./vs/workbench/browser/parts/editor/editorDropTarget.ts", "./vs/workbench/browser/parts/editor/editorPicker.ts", "./vs/workbench/browser/parts/editor/editorWidgets.ts", + "./vs/workbench/browser/parts/editor/noTabsTitleControl.ts", "./vs/workbench/browser/parts/editor/rangeDecorations.ts", "./vs/workbench/browser/parts/editor/resourceViewer.ts", "./vs/workbench/browser/parts/editor/sideBySideEditor.ts", + "./vs/workbench/browser/parts/editor/tabsTitleControl.ts", "./vs/workbench/browser/parts/editor/textDiffEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", "./vs/workbench/browser/parts/editor/textResourceEditor.ts", diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 4e1e729e2b7..e250e63ab42 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -16,7 +16,7 @@ import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/edito import { Color } from 'vs/base/common/color'; interface IRenderedEditorLabel { - editor: IEditorInput; + editor?: IEditorInput; pinned: boolean; } @@ -72,8 +72,16 @@ export class NoTabsTitleControl extends TitleControl { this._register(addDisposableListener(this.titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e))); // Context Menu - this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer))); - this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer))); + this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => { + if (this.group.activeEditor) { + this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + } + })); + this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => { + if (this.group.activeEditor) { + this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + } + })); } private onTitleLabelClick(e: MouseEvent): void { @@ -95,7 +103,9 @@ export class NoTabsTitleControl extends TitleControl { if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) { EventHelper.stop(e, true /* for https://github.com/Microsoft/vscode/issues/56715 */); - this.group.closeEditor(this.group.activeEditor); + if (this.group.activeEditor) { + this.group.closeEditor(this.group.activeEditor); + } } } @@ -167,7 +177,7 @@ export class NoTabsTitleControl extends TitleControl { if ( !this.activeLabel.editor && this.group.activeEditor || // active editor changed from null => editor this.activeLabel.editor && !this.group.activeEditor || // active editor changed from editor => null - !this.group.isActive(this.activeLabel.editor) // active editor changed from editorA => editorB + (!this.activeLabel.editor || !this.group.isActive(this.activeLabel.editor)) // active editor changed from editorA => editorB ) { fn(); @@ -197,10 +207,10 @@ export class NoTabsTitleControl extends TitleControl { private redraw(): void { const editor = this.group.activeEditor; - const isEditorPinned = this.group.isPinned(this.group.activeEditor); + const isEditorPinned = this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false; const isGroupActive = this.accessor.activeGroup === this.group; - this.activeLabel = { editor, pinned: isEditorPinned }; + this.activeLabel = { editor: editor || undefined, pinned: isEditorPinned }; // Update Breadcrumbs if (this.breadcrumbsControl) { @@ -244,7 +254,7 @@ export class NoTabsTitleControl extends TitleControl { title = ''; // dont repeat what is already shown } - this.editorLabel.setResource({ name, description, resource: resource || undefined }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] }); + this.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); } else { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index e2bfb8d2cd7..aa38992e096 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -212,7 +212,7 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + 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; @@ -469,7 +469,10 @@ export class TabsTitleControl extends TitleControl { } // Open tabs editor - this.group.openEditor(this.group.getEditor(index)); + const input = this.group.getEditor(index); + if (input) { + this.group.openEditor(input); + } return undefined; }; @@ -477,7 +480,10 @@ export class TabsTitleControl extends TitleControl { const showContextMenu = (e: Event) => { EventHelper.stop(e); - this.onContextMenu(this.group.getEditor(index), e, tab); + const input = this.group.getEditor(index); + if (input) { + this.onContextMenu(input, e, tab); + } }; // Open on Click / Touch @@ -524,7 +530,10 @@ export class TabsTitleControl extends TitleControl { // Run action on Enter/Space if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { handled = true; - this.group.openEditor(this.group.getEditor(index)); + const input = this.group.getEditor(index); + if (input) { + this.group.openEditor(input); + } } // Navigate in editors @@ -569,12 +578,19 @@ export class TabsTitleControl extends TitleControl { disposables.push(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: Event) => { EventHelper.stop(e, true); - this.onContextMenu(this.group.getEditor(index), e, tab); + const input = this.group.getEditor(index); + if (input) { + this.onContextMenu(input, e, tab); + } }, true /* use capture to fix https://github.com/Microsoft/vscode/issues/19145 */)); // Drag support disposables.push(addDisposableListener(tab, EventType.DRAG_START, (e: DragEvent) => { const editor = this.group.getEditor(index); + if (!editor) { + return; + } + this.editorTransfer.setData([new DraggedEditorIdentifier({ editor, groupId: this.group.id })], DraggedEditorIdentifier.prototype); e.dataTransfer!.effectAllowed = 'copyMove'; @@ -608,7 +624,7 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + 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; @@ -649,7 +665,7 @@ export class TabsTitleControl extends TitleControl { private isSupportedDropTransfer(e: DragEvent): boolean { if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0]; + 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 } @@ -764,7 +780,7 @@ export class TabsTitleControl extends TitleControl { // Remove description if all descriptions are identical if (descriptions.length === 1) { - for (const label of mapDescriptionToDuplicates.get(descriptions[0])) { + for (const label of mapDescriptionToDuplicates.get(descriptions[0]) || []) { label.description = ''; } @@ -774,7 +790,7 @@ export class TabsTitleControl extends TitleControl { // Shorten descriptions const shortenedDescriptions = shorten(descriptions); descriptions.forEach((description, i) => { - for (const label of mapDescriptionToDuplicates.get(description)) { + for (const label of mapDescriptionToDuplicates.get(description) || []) { label.description = shortenedDescriptions[i]; } }); @@ -860,7 +876,7 @@ export class TabsTitleControl extends TitleControl { tabContainer.title = title; // Label - tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }); + tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) || undefined }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }); } private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void { @@ -963,7 +979,7 @@ export class TabsTitleControl extends TitleControl { layout(dimension: Dimension): void { this.dimension = dimension; - const activeTab = this.getTab(this.group.activeEditor); + const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined; if (!activeTab || !this.dimension) { return; } @@ -980,7 +996,7 @@ export class TabsTitleControl extends TitleControl { } private doLayout(dimension: Dimension): void { - const activeTab = this.getTab(this.group.activeEditor); + const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined; if (!activeTab) { return; } @@ -993,8 +1009,8 @@ export class TabsTitleControl extends TitleControl { const visibleContainerWidth = this.tabsContainer.offsetWidth; const totalContainerWidth = this.tabsContainer.scrollWidth; - let activeTabPosX: number | undefined; - let activeTabWidth: number | undefined; + let activeTabPosX: number; + let activeTabWidth: number; if (!this.blockRevealActiveTab) { activeTabPosX = activeTab.offsetLeft; @@ -1015,20 +1031,20 @@ export class TabsTitleControl extends TitleControl { // 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! }); } } @@ -1071,7 +1087,7 @@ export class TabsTitleControl extends TitleControl { // Local Editor DND if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); // Move editor to target position and index @@ -1090,7 +1106,7 @@ export class TabsTitleControl extends TitleControl { // Local Editor Group DND else if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier); + const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier); const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex }; if (!this.isMoveOperation(e, sourceGroup.id)) { @@ -1119,7 +1135,8 @@ export class TabsTitleControl extends TitleControl { dispose(): void { super.dispose(); - this.layoutScheduled = dispose(this.layoutScheduled); + dispose(this.layoutScheduled); + this.layoutScheduled = undefined; } } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index eb745aa83fc..a254b632c2e 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -974,7 +974,7 @@ export interface IResourceOptions { filter?: string | string[]; } -export function toResource(editor: IEditorInput, options?: IResourceOptions): URI | null { +export function toResource(editor: IEditorInput | null, options?: IResourceOptions): URI | null { if (!editor) { return null; } From 0589591234175143ca39cc9363d93a4fb30134ce Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 16:01:57 -0800 Subject: [PATCH 093/172] Strict null work in editorGroupView --- src/vs/base/browser/dom.ts | 2 +- .../actions/browser/menuItemActionItem.ts | 2 +- src/vs/workbench/browser/legacyLayout.ts | 10 ++--- .../parts/editor/editor.contribution.ts | 2 +- .../browser/parts/editor/editorGroupView.ts | 44 ++++++++++++------- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 2ac95d2b9c6..b74f87d67a3 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -615,7 +615,7 @@ export interface IDomNodePagePosition { height: number; } -export function size(element: HTMLElement, width: number, height: number): void { +export function size(element: HTMLElement, width: number | null, height: number | null): void { if (typeof width === 'number') { element.style.width = `${width}px`; } diff --git a/src/vs/platform/actions/browser/menuItemActionItem.ts b/src/vs/platform/actions/browser/menuItemActionItem.ts index 872b66f8e5a..8b0275c16cc 100644 --- a/src/vs/platform/actions/browser/menuItemActionItem.ts +++ b/src/vs/platform/actions/browser/menuItemActionItem.ts @@ -76,7 +76,7 @@ class AlternativeKeyEmitter extends Emitter { } } -export function fillInContextMenuActions(menu: IMenu, options: IMenuActionOptions, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, contextMenuService: IContextMenuService, isPrimaryGroup?: (group: string) => boolean): void { +export function fillInContextMenuActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, contextMenuService: IContextMenuService, isPrimaryGroup?: (group: string) => boolean): void { const groups = menu.getActions(options); const getAlternativeActions = AlternativeKeyEmitter.getInstance(contextMenuService).isPressed; diff --git a/src/vs/workbench/browser/legacyLayout.ts b/src/vs/workbench/browser/legacyLayout.ts index 1d91550fcab..e47480d7e9f 100644 --- a/src/vs/workbench/browser/legacyLayout.ts +++ b/src/vs/workbench/browser/legacyLayout.ts @@ -388,9 +388,9 @@ export class WorkbenchLegacyLayout extends Disposable implements IVerticalSashLa })); this._register(this.sashXOne.onDidReset(() => { - let activeViewlet = this.viewletService.getActiveViewlet(); - let optimalWidth = activeViewlet && activeViewlet.getOptimalWidth(); - this.sidebarWidth = Math.max(optimalWidth, DEFAULT_SIDEBAR_PART_WIDTH); + const activeViewlet = this.viewletService.getActiveViewlet(); + const optimalWidth = activeViewlet ? activeViewlet.getOptimalWidth() : null; + this.sidebarWidth = typeof optimalWidth === 'number' ? Math.max(optimalWidth, DEFAULT_SIDEBAR_PART_WIDTH) : DEFAULT_SIDEBAR_PART_WIDTH; this.storageService.store(WorkbenchLegacyLayout.sashXOneWidthSettingsKey, this.sidebarWidth, StorageScope.GLOBAL); this.partService.setSideBarHidden(false); @@ -596,10 +596,10 @@ export class WorkbenchLegacyLayout extends Disposable implements IVerticalSashLa size(activitybarContainer, null, activityBarSize.height); if (sidebarPosition === Position.LEFT) { this.parts.activitybar.getContainer().style.right = ''; - position(activitybarContainer, this.titlebarHeight, null, 0, 0); + position(activitybarContainer, this.titlebarHeight, undefined, 0, 0); } else { this.parts.activitybar.getContainer().style.left = ''; - position(activitybarContainer, this.titlebarHeight, 0, 0, null); + position(activitybarContainer, this.titlebarHeight, 0, 0, undefined); } if (isActivityBarHidden) { hide(activitybarContainer); diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 5c1e6ef0f87..2daccc8005a 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -103,7 +103,7 @@ Registry.as(EditorExtensions.Editors).registerEditor( interface ISerializedUntitledEditorInput { resource: string; resourceJSON: object; - modeId: string; + modeId: string | null; encoding: string; } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 0a3d443d567..421352abd2a 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -411,6 +411,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } const activeEditor = this._group.activeEditor; + if (!activeEditor) { + return Promise.resolve(); + } + options.pinned = this._group.isPinned(activeEditor); // preserve pinned state options.preserveFocus = true; // handle focus after editor is opened @@ -561,7 +565,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Pin preview editor once user disables preview if (event.oldPartOptions.enablePreview && !event.newPartOptions.enablePreview) { - this.pinEditor(this._group.previewEditor); + if (this._group.previewEditor) { + this.pinEditor(this._group.previewEditor); + } } } @@ -705,7 +711,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this._onDidFocus.fire(); } - pinEditor(editor: EditorInput = this.activeEditor): void { + pinEditor(editor: EditorInput | undefined = this.activeEditor || undefined): void { if (editor && !this._group.isPinned(editor)) { // Update model @@ -743,7 +749,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return this.doOpenEditor(editor, options); } - private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise { + private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise { // Determine options const openEditorOptions: IEditorOpenOptions = { @@ -752,7 +758,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { active: this._group.count === 0 || !options || !options.inactive }; - if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.isPreview(this._group.activeEditor)) { + if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && this._group.isPreview(this._group.activeEditor)) { // Special case: we are to open an editor inactive and not pinned, but the current active // editor is also not pinned, which means it will get replaced with this one. As such, // the editor can only be active. @@ -781,13 +787,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this._group.openEditor(editor, openEditorOptions); // Show editor - return this.doShowEditor(editor, openEditorOptions.active, options); + return this.doShowEditor(editor, !!openEditorOptions.active, options); } - private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise { + private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise { // Show in editor control if the active editor changed - let openEditorPromise: Promise; + let openEditorPromise: Promise; if (active) { openEditorPromise = this.editorControl.openEditor(editor, options).then(result => { @@ -830,7 +836,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { actions }); - Event.once(handle.onDidClose)(() => dispose(actions.primary)); + Event.once(handle.onDidClose)(() => actions.primary && dispose(actions.primary)); } // Event @@ -855,7 +861,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Do not modify original array editors = editors.slice(0); - let result: IEditor; + let result: IEditor | null; // Use the first editor as active editor const { editor, options } = editors.shift()!; @@ -958,7 +964,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region closeEditor() - closeEditor(editor: EditorInput = this.activeEditor, options?: ICloseEditorOptions): Promise { + closeEditor(editor: EditorInput | undefined = this.activeEditor || undefined, options?: ICloseEditorOptions): Promise { if (!editor) { return Promise.resolve(); } @@ -1015,7 +1021,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } // Update model - this._group.closeEditor(editorToClose); + if (editorToClose) { + this._group.closeEditor(editorToClose); + } // Open next active if there are more to show const nextActiveEditor = this._group.activeEditor; @@ -1038,7 +1046,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { else { // Forward to editor control - this.editorControl.closeEditor(editorToClose); + if (editorToClose) { + this.editorControl.closeEditor(editorToClose); + } // Restore focus to group container as needed unless group gets closed if (restoreFocus && !closeEmptyGroup) { @@ -1077,7 +1087,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return Promise.resolve(false); // no veto } - const editor = editors.shift(); + const editor = editors.shift()!; // To prevent multiple confirmation dialogs from showing up one after the other // we check if a pending confirmation is currently showing and if so, join that @@ -1376,8 +1386,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView { get maximumWidth(): number { return this.editorControl.maximumWidth; } get maximumHeight(): number { return this.editorControl.maximumHeight; } - private _onDidChange = this._register(new Relay<{ width: number; height: number; }>()); - readonly onDidChange: Event<{ width: number; height: number; }> = this._onDidChange.event; + private _onDidChange = this._register(new Relay<{ width: number; height: number; } | undefined>()); + readonly onDidChange: Event<{ width: number; height: number; } | undefined> = this._onDidChange.event; layout(width: number, height: number): void { this.dimension = new Dimension(width, height); @@ -1422,7 +1432,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent { constructor( private _group: GroupIdentifier, private _editor: EditorInput, - private _options: EditorOptions + private _options: EditorOptions | undefined ) { } @@ -1434,7 +1444,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent { return this._editor; } - get options(): EditorOptions { + get options(): EditorOptions | undefined { return this._options; } From 6937635d1d6e132d5cdbe68f82d3a1e8a36cf712 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 16:28:07 -0800 Subject: [PATCH 094/172] Supress some strict null errors in mainThreadSavePartcipants --- .../api/mainThreadSaveParticipant.test.ts | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts index 2cc91becc3c..6fc405bc679 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts @@ -47,27 +47,27 @@ suite('MainThreadSaveParticipant', function () { // No new line for empty lines let lineContent = ''; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // No new line if last line already empty - lineContent = `Hello New Line${model.textEditorModel.getEOL()}`; - model.textEditorModel.setValue(lineContent); + lineContent = `Hello New Line${model.textEditorModel!.getEOL()}`; + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // New empty line added (single line) lineContent = 'Hello New Line'; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel!.getEOL()}`); // New empty line added (multi line) - lineContent = `Hello New Line${model.textEditorModel.getEOL()}Hello New Line${model.textEditorModel.getEOL()}Hello New Line`; - model.textEditorModel.setValue(lineContent); + lineContent = `Hello New Line${model.textEditorModel!.getEOL()}Hello New Line${model.textEditorModel!.getEOL()}Hello New Line`; + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel!.getEOL()}`); }); test('trim final new lines', async function () { @@ -78,29 +78,29 @@ suite('MainThreadSaveParticipant', function () { configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); const participant = new TrimFinalNewLinesParticipant(configService, undefined!); const textContent = 'Trim New Line'; - const eol = `${model.textEditorModel.getEOL()}`; + const eol = `${model.textEditorModel!.getEOL()}`; // No new line removal if last line is not new line let lineContent = `${textContent}`; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // No new line removal if last line is single new line lineContent = `${textContent}${eol}`; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // Remove new line (single line with two new lines) lineContent = `${textContent}${eol}${eol}`; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); // Remove new lines (multiple lines with multiple new lines) lineContent = `${textContent}${eol}${textContent}${eol}${eol}${eol}`; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}${textContent}${eol}`); }); @@ -116,33 +116,33 @@ suite('MainThreadSaveParticipant', function () { // single line let lineContent = `${textContent}`; - model.textEditorModel.setValue(lineContent); + model.textEditorModel!.setValue(lineContent); // apply edits and push to undo stack. let textEdits = [{ range: new Range(1, 14, 1, 14), text: '.', forceMoveMarkers: false }]; - model.textEditorModel.pushEditOperations([new Selection(1, 14, 1, 14)], textEdits, () => { return [new Selection(1, 15, 1, 15)]; }); + model.textEditorModel!.pushEditOperations([new Selection(1, 14, 1, 14)], textEdits, () => { return [new Selection(1, 15, 1, 15)]; }); // undo - model.textEditorModel.undo(); + model.textEditorModel!.undo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}`); // trim final new lines should not mess the undo stack await participant.participate(model, { reason: SaveReason.EXPLICIT }); - model.textEditorModel.redo(); + model.textEditorModel!.redo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}.`); }); test('trim final new lines bug#46075', async function () { - const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); await model.load(); const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); const participant = new TrimFinalNewLinesParticipant(configService, undefined!); const textContent = 'Test'; - const eol = `${model.textEditorModel.getEOL()}`; + const eol = `${model.textEditorModel!.getEOL()}`; let content = `${textContent}${eol}${eol}`; - model.textEditorModel.setValue(content); + model.textEditorModel!.setValue(content); // save many times for (let i = 0; i < 10; i++) { @@ -153,9 +153,9 @@ suite('MainThreadSaveParticipant', function () { assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); // undo should go back to previous content immediately - model.textEditorModel.undo(); + model.textEditorModel!.undo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}${eol}`); - model.textEditorModel.redo(); + model.textEditorModel!.redo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); }); }); From 6f6aa562755e5b8df57760ad34f741ab6b9827bb Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 16:33:56 -0800 Subject: [PATCH 095/172] Strict null work in keybindingsEditorContribution --- .../browser/keybindingsEditorContribution.ts | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts index 35f7916e436..06dec075f30 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts @@ -14,7 +14,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { registerEditorContribution, ServicesAccessor, registerEditorCommand, EditorCommand } from 'vs/editor/browser/editorExtensions'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; import { SmartSnippetInserter } from 'vs/workbench/contrib/preferences/common/smartSnippetInserter'; import { DefineKeybindingOverlayWidget } from 'vs/workbench/contrib/preferences/browser/keybindingWidgets'; @@ -42,8 +42,8 @@ export class DefineKeybindingController extends Disposable implements editorComm return editor.getContribution(DefineKeybindingController.ID); } - private _keybindingWidgetRenderer: KeybindingWidgetRenderer; - private _keybindingDecorationRenderer: KeybindingEditorDecorationsRenderer; + private _keybindingWidgetRenderer?: KeybindingWidgetRenderer; + private _keybindingDecorationRenderer?: KeybindingEditorDecorationsRenderer; constructor( private _editor: ICodeEditor, @@ -51,9 +51,6 @@ export class DefineKeybindingController extends Disposable implements editorComm ) { super(); - this._keybindingWidgetRenderer = null; - this._keybindingDecorationRenderer = null; - this._register(this._editor.onDidChangeModel(e => this._update())); this._update(); } @@ -62,7 +59,7 @@ export class DefineKeybindingController extends Disposable implements editorComm return DefineKeybindingController.ID; } - get keybindingWidgetRenderer(): KeybindingWidgetRenderer { + get keybindingWidgetRenderer(): KeybindingWidgetRenderer | undefined { return this._keybindingWidgetRenderer; } @@ -99,7 +96,7 @@ export class DefineKeybindingController extends Disposable implements editorComm private _disposeKeybindingWidgetRenderer(): void { if (this._keybindingWidgetRenderer) { this._keybindingWidgetRenderer.dispose(); - this._keybindingWidgetRenderer = null; + this._keybindingWidgetRenderer = undefined; } } @@ -112,7 +109,7 @@ export class DefineKeybindingController extends Disposable implements editorComm private _disposeKeybindingDecorationRenderer(): void { if (this._keybindingDecorationRenderer) { this._keybindingDecorationRenderer.dispose(); - this._keybindingDecorationRenderer = null; + this._keybindingDecorationRenderer = undefined; } } } @@ -140,7 +137,7 @@ export class KeybindingWidgetRenderer extends Disposable { private _onAccepted(keybinding: string): void { this._editor.focus(); - if (keybinding) { + if (keybinding && this._editor.hasModel()) { const regexp = new RegExp(/\\/g); const backslash = regexp.test(keybinding); if (backslash) { @@ -169,7 +166,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { private _dec: string[] = []; constructor( - private _editor: ICodeEditor, + private _editor: IActiveCodeEditor, @IKeybindingService private readonly _keybindingService: IKeybindingService, ) { super(); @@ -207,7 +204,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { this._dec = this._editor.deltaDecorations(this._dec, newDecorations); } - private _getDecorationForEntry(model: ITextModel, entry: Node): IModelDeltaDecoration { + private _getDecorationForEntry(model: ITextModel, entry: Node): IModelDeltaDecoration | null { if (!Array.isArray(entry.children)) { return null; } @@ -239,7 +236,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { } if (!resolvedKeybinding.isWYSIWYG()) { const uiLabel = resolvedKeybinding.getLabel(); - if (value.value.toLowerCase() === uiLabel.toLowerCase()) { + if (typeof uiLabel === 'string' && value.value.toLowerCase() === uiLabel.toLowerCase()) { // coincidentally, this is actually WYSIWYG return null; } @@ -249,7 +246,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { return this._createDecoration(false, resolvedKeybinding.getLabel(), usLabel, model, value); } const expectedUserSettingsLabel = resolvedKeybinding.getUserSettingsLabel(); - if (!KeybindingEditorDecorationsRenderer._userSettingsFuzzyEquals(value.value, expectedUserSettingsLabel)) { + if (typeof expectedUserSettingsLabel === 'string' && !KeybindingEditorDecorationsRenderer._userSettingsFuzzyEquals(value.value, expectedUserSettingsLabel)) { return this._createDecoration(false, resolvedKeybinding.getLabel(), usLabel, model, value); } return null; @@ -300,7 +297,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { return false; } - private _createDecoration(isError: boolean, uiLabel: string, usLabel: string, model: ITextModel, keyNode: Node): IModelDeltaDecoration { + private _createDecoration(isError: boolean, uiLabel: string | null, usLabel: string | null, model: ITextModel, keyNode: Node): IModelDeltaDecoration { let msg: MarkdownString; let className: string; let beforeContentClassName: string; From 243d3a482b65de5cb24df6e8962dc1a17f3b9940 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 21:41:01 -0800 Subject: [PATCH 096/172] Strict null work in menubar --- src/vs/base/browser/ui/menu/menubar.ts | 2 +- src/vs/platform/menubar/common/menubar.ts | 2 +- .../browser/parts/titlebar/menubarControl.ts | 45 +++++++++++-------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index 4506ec9f488..289bfd8f369 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -22,7 +22,7 @@ const $ = DOM.$; export interface IMenuBarOptions { enableMnemonics?: boolean; visibility?: string; - getKeybinding?: (action: IAction) => ResolvedKeybinding; + getKeybinding?: (action: IAction) => ResolvedKeybinding | undefined; alwaysOnMnemonics?: boolean; } diff --git a/src/vs/platform/menubar/common/menubar.ts b/src/vs/platform/menubar/common/menubar.ts index 84ceaf14ec2..27294cbb3aa 100644 --- a/src/vs/platform/menubar/common/menubar.ts +++ b/src/vs/platform/menubar/common/menubar.ts @@ -25,7 +25,7 @@ export interface IMenubarMenu { export interface IMenubarKeybinding { label: string; - userSettingsLabel: string; + userSettingsLabel?: string; isNative?: boolean; // Assumed true if missing } diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 254ae288772..0399029f2e6 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -58,7 +58,7 @@ export class MenubarControl extends Disposable { 'Terminal': IMenu; 'Window'?: IMenu; 'Help': IMenu; - [index: string]: IMenu; + [index: string]: IMenu | undefined; }; private topLevelTitles = { @@ -121,8 +121,11 @@ export class MenubarControl extends Disposable { this.menuUpdater = this._register(new RunOnceScheduler(() => this.doUpdateMenubar(false), 200)); if (isMacintosh || this.currentTitlebarStyleSetting !== 'custom') { - for (let topLevelMenuName of Object.keys(this.topLevelMenus)) { - this._register(this.topLevelMenus[topLevelMenuName].onDidChange(() => this.updateMenubar())); + for (const topLevelMenuName of Object.keys(this.topLevelMenus)) { + const menu = this.topLevelMenus[topLevelMenuName]; + if (menu) { + this._register(menu.onDidChange(() => this.updateMenubar())); + } } this.doUpdateMenubar(true); @@ -441,7 +444,7 @@ export class MenubarControl extends Disposable { return new Action('update.checking', nls.localize('checkingForUpdates', "Checking For Updates..."), undefined, false); case StateType.AvailableForDownload: - return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Now"), null, true, () => + return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Now"), undefined, true, () => this.updateService.downloadUpdate()); case StateType.Downloading: @@ -533,9 +536,9 @@ export class MenubarControl extends Disposable { target.pop(); }; - for (let title of Object.keys(this.topLevelMenus)) { + for (const title of Object.keys(this.topLevelMenus)) { const menu = this.topLevelMenus[title]; - if (firstTime) { + if (firstTime && menu) { this._register(menu.onDidChange(() => { const actions = []; updateActions(menu, actions); @@ -544,7 +547,9 @@ export class MenubarControl extends Disposable { } const actions = []; - updateActions(menu, actions); + if (menu) { + updateActions(menu, actions); + } if (!firstTime) { this.menubar.updateMenu({ actions: actions, label: mnemonicMenuLabel(this.topLevelTitles[title]) }); @@ -554,7 +559,7 @@ export class MenubarControl extends Disposable { } } - private getMenubarKeybinding(id: string): IMenubarKeybinding { + private getMenubarKeybinding(id: string): IMenubarKeybinding | undefined { const binding = this.keybindingService.lookupKeybinding(id); if (!binding) { return undefined; @@ -563,19 +568,19 @@ export class MenubarControl extends Disposable { // first try to resolve a native accelerator const electronAccelerator = binding.getElectronAccelerator(); if (electronAccelerator) { - return { label: electronAccelerator, userSettingsLabel: binding.getUserSettingsLabel() }; + return { label: electronAccelerator, userSettingsLabel: binding.getUserSettingsLabel() || undefined }; } // we need this fallback to support keybindings that cannot show in electron menus (e.g. chords) const acceleratorLabel = binding.getLabel(); if (acceleratorLabel) { - return { label: acceleratorLabel, isNative: false, userSettingsLabel: binding.getUserSettingsLabel() }; + return { label: acceleratorLabel, isNative: false, userSettingsLabel: binding.getUserSettingsLabel() || undefined }; } - return null; + return undefined; } - private populateMenuItems(menu: IMenu, menuToPopulate: IMenubarMenu, keybindings: { [id: string]: IMenubarKeybinding }) { + private populateMenuItems(menu: IMenu, menuToPopulate: IMenubarMenu, keybindings: { [id: string]: IMenubarKeybinding | undefined }) { let groups = menu.getActions(); for (let group of groups) { const [, actions] = group; @@ -643,15 +648,17 @@ export class MenubarControl extends Disposable { } menubarData.keybindings = this.getAdditionalKeybindings(); - for (let topLevelMenuName of Object.keys(this.topLevelMenus)) { + for (const topLevelMenuName of Object.keys(this.topLevelMenus)) { const menu = this.topLevelMenus[topLevelMenuName]; - let menubarMenu: IMenubarMenu = { items: [] }; - this.populateMenuItems(menu, menubarMenu, menubarData.keybindings); - if (menubarMenu.items.length === 0) { - // Menus are incomplete - return false; + if (menu) { + const menubarMenu: IMenubarMenu = { items: [] }; + this.populateMenuItems(menu, menubarMenu, menubarData.keybindings); + if (menubarMenu.items.length === 0) { + // Menus are incomplete + return false; + } + menubarData.menus[topLevelMenuName] = menubarMenu; } - menubarData.menus[topLevelMenuName] = menubarMenu; } return true; From 3bb9487c4f7ae17d39613e72a9342c7879c64569 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 21:46:27 -0800 Subject: [PATCH 097/172] Strict null check backupModelTracker --- src/tsconfig.strictNullChecks.json | 3 +++ .../contrib/backup/common/backupModelTracker.ts | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 835e5e859a2..218d13ddc5b 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -121,6 +121,7 @@ "./vs/workbench/browser/parts/editor/editorCommands.ts", "./vs/workbench/browser/parts/editor/editorControl.ts", "./vs/workbench/browser/parts/editor/editorDropTarget.ts", + "./vs/workbench/browser/parts/editor/editorGroupView.ts", "./vs/workbench/browser/parts/editor/editorPicker.ts", "./vs/workbench/browser/parts/editor/editorWidgets.ts", "./vs/workbench/browser/parts/editor/noTabsTitleControl.ts", @@ -176,6 +177,8 @@ "./vs/workbench/common/theme.ts", "./vs/workbench/common/viewlet.ts", "./vs/workbench/common/views.ts", + "./vs/workbench/contrib/backup/common/backup.contribution.ts", + "./vs/workbench/contrib/backup/common/backupModelTracker.ts", "./vs/workbench/contrib/backup/common/backupRestorer.ts", "./vs/workbench/contrib/cli/node/cli.contribution.ts", "./vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.ts", diff --git a/src/vs/workbench/contrib/backup/common/backupModelTracker.ts b/src/vs/workbench/contrib/backup/common/backupModelTracker.ts index 68a433394c4..2b245986c9b 100644 --- a/src/vs/workbench/contrib/backup/common/backupModelTracker.ts +++ b/src/vs/workbench/contrib/backup/common/backupModelTracker.ts @@ -65,14 +65,24 @@ export class BackupModelTracker extends Disposable implements IWorkbenchContribu // Do not backup when auto save after delay is configured if (!this.configuredAutoSaveAfterDelay) { const model = this.textFileService.models.get(event.resource); - this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId()); + if (model) { + const snapshot = model.createSnapshot(); + if (snapshot) { + this.backupFileService.backupResource(model.getResource(), snapshot, model.getVersionId()); + } + } } } } private onUntitledModelChanged(resource: Uri): void { if (this.untitledEditorService.isDirty(resource)) { - this.untitledEditorService.loadOrCreate({ resource }).then(model => this.backupFileService.backupResource(resource, model.createSnapshot(), model.getVersionId())); + this.untitledEditorService.loadOrCreate({ resource }).then(model => { + const snapshot = model.createSnapshot(); + if (snapshot) { + this.backupFileService.backupResource(resource, snapshot, model.getVersionId()); + } + }); } else { this.discardBackup(resource); } From 713b178898d61d0b68677f41ed58ab2547e68cc5 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 21:50:00 -0800 Subject: [PATCH 098/172] Strict null work openEditor can return null --- .../localizations/browser/localizationsActions.ts | 6 +++--- .../services/editor/browser/editorService.ts | 12 ++++++------ .../services/editor/common/editorService.ts | 8 ++++---- src/vs/workbench/services/history/browser/history.ts | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts index 62f41d1a3fd..3ee31d1c836 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts @@ -36,13 +36,13 @@ export class ConfigureLocaleAction extends Action { super(id, label); } - public run(event?: any): Promise { + public run(event?: any): Promise { const file = URI.file(join(this.environmentService.appSettingsHome, 'locale.json')); return this.fileService.resolveFile(file).then(undefined, (error) => { return this.fileService.createFile(file, ConfigureLocaleAction.DEFAULT_CONTENT); - }).then((stat): Promise | undefined => { + }).then((stat): Promise | null => { if (!stat) { - return undefined; + return null; } return this.editorService.openEditor({ resource: stat.resource diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index b9665358c3b..9e498cf51b4 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -214,11 +214,11 @@ export class EditorService extends Disposable implements EditorServiceImpl { //#region openEditor() - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceDiffInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceSideBySideInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IEditorInput | IResourceEditor, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: GroupIdentifier): Promise { + openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceDiffInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceSideBySideInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IEditorInput | IResourceEditor, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: GroupIdentifier): Promise { // Typed Editor Support if (editor instanceof EditorInput) { @@ -241,7 +241,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { return Promise.resolve(null); } - protected doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise { + protected doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise { return group.openEditor(editor, options); } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 18fb4e87975..476c374d219 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -119,10 +119,10 @@ export interface IEditorService { * @returns the editor that opened or NULL if the operation failed or the editor was not * opened to be active. */ - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceDiffInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceSideBySideInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceDiffInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceSideBySideInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; /** * Open editors in an editor group. diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 03234a94c8e..7f52cda2121 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -420,7 +420,7 @@ export class HistoryService extends Disposable implements IHistoryService { this.doNavigate(this.stack[this.index], !acrossEditors).finally(() => this.navigatingInStack = false); } - private doNavigate(location: IStackEntry, withSelection: boolean): Promise { + private doNavigate(location: IStackEntry, withSelection: boolean): Promise { const options: ITextEditorOptions = { revealIfOpened: true // support to navigate across editor groups }; From d3f079fd7ac0b5c81fc66f7b326f37bc24a03a97 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 21:58:13 -0800 Subject: [PATCH 099/172] Mark fields readonly --- src/vs/workbench/common/editor.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index a254b632c2e..2a958ad5466 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -533,7 +533,12 @@ export class SideBySideEditorInput extends EditorInput { static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; - constructor(private name: string, private description: string | null, private _details: EditorInput, private _master: EditorInput) { + constructor( + private readonly name: string, + private readonly description: string | null, + private readonly _details: EditorInput, + private readonly _master: EditorInput + ) { super(); this.registerListeners(); From 181ab9f3db4c7ef2c7be00e6ab6252f36d689308 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 22:00:04 -0800 Subject: [PATCH 100/172] Strict null work on editorService --- src/vs/workbench/common/editor.ts | 4 ++-- src/vs/workbench/services/editor/browser/editorService.ts | 4 ++-- src/vs/workbench/services/editor/common/editorService.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2a958ad5466..fb00992d23e 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -760,9 +760,9 @@ export class TextEditorOptions extends EditorOptions { private revealInCenterIfOutsideViewport: boolean; private editorViewState: IEditorViewState | null; - static from(input?: IBaseResourceInput): TextEditorOptions | null { + static from(input?: IBaseResourceInput): TextEditorOptions | undefined { if (!input || !input.options) { - return null; + return undefined; } return TextEditorOptions.create(input.options); diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 9e498cf51b4..d04efc8119d 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -377,7 +377,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { //#region getOpend() - getOpened(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput { + getOpened(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput | undefined { return this.doGetOpened(editor); } @@ -626,7 +626,7 @@ export class DelegatingEditorService extends EditorService { this.editorOpenHandler = handler; } - protected doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise { + protected doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise { if (!this.editorOpenHandler) { return super.doOpenEditor(group, editor, options); } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 476c374d219..e47ffb540bf 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -166,7 +166,7 @@ export interface IEditorService { * * @param group optional to specify a group to check for the editor */ - getOpened(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput; + getOpened(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput | undefined; /** * Allows to override the opening of editors by installing a handler that will From 7d8845205932983b4029ad58a42385c7a65d3729 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 09:16:17 -0800 Subject: [PATCH 101/172] Strict null check mainThreadSaveParticpants --- src/tsconfig.strictNullChecks.json | 1 + .../mainThreadSaveParticipant.ts | 16 ++++++++-------- .../textfile/common/textFileEditorModel.ts | 4 ++-- .../services/textfile/common/textfiles.ts | 8 ++++++-- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 218d13ddc5b..ff390f15cb9 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -32,6 +32,7 @@ "./vs/workbench/services/timer/**/*.ts" ], "files": [ + "./vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts", "./vs/monaco.d.ts", "./vs/nls.d.ts", "./vs/nls.mock.ts", diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 2c4068005f8..36490d0f2fe 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -34,7 +34,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; -import { ISaveParticipant, ITextFileEditorModel, SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; +import { ISaveParticipant, SaveReason, IActiveTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../node/extHost.protocol'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -51,7 +51,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IActiveTextFileEditorModel, 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); } @@ -113,7 +113,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doInsertFinalNewLine(model.textEditorModel); } @@ -151,7 +151,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant // Nothing } - async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IActiveTextFileEditorModel, 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); } @@ -222,7 +222,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { const model = editorModel.textEditorModel; if (env.reason === SaveReason.AUTO @@ -293,7 +293,7 @@ class CodeActionOnSaveParticipant implements ISaveParticipant { @IConfigurationService private readonly _configurationService: IConfigurationService ) { } - async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { if (env.reason === SaveReason.AUTO) { return undefined; } @@ -373,7 +373,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant); } - async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { if (!shouldSynchronizeModel(editorModel.textEditorModel)) { // the model never made it to the extension @@ -424,7 +424,7 @@ export class SaveParticipant implements ISaveParticipant { this._saveParticipants.dispose(); } - async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(model: IActiveTextFileEditorModel, 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/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 64f2a50b4dc..870f66a51f7 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { isUndefinedOrNull } 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, IRawTextContent, ILoadOptions, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions, LoadReason, IActiveTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -661,7 +661,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil }; this.blockModelContentChange = true; - saveParticipantPromise = TextFileEditorModel.saveParticipant.participate(this, { reason: options.reason }).then(onCompleteOrError, onCompleteOrError); + saveParticipantPromise = TextFileEditorModel.saveParticipant.participate(this as IActiveTextFileEditorModel, { reason: options.reason }).then(onCompleteOrError, onCompleteOrError); } // mark the save participant as current pending save operation diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index a51df6695ac..d9c897b069c 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -10,7 +10,7 @@ import { IEncodingSupport, ConfirmResult, IRevertOptions } from 'vs/workbench/co import { IBaseStat, IResolveContentOptions, ITextSnapshot } from 'vs/platform/files/common/files'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; -import { ITextBufferFactory } from 'vs/editor/common/model'; +import { ITextBufferFactory, ITextModel } from 'vs/editor/common/model'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; /** @@ -29,7 +29,7 @@ export interface ISaveParticipant { /** * Participate in a save of a model. Allows to change the model before it is being saved to disk. */ - participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise; + participate(model: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise; } /** @@ -255,6 +255,10 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport isDisposed(): boolean; } +export interface IActiveTextFileEditorModel extends ITextFileEditorModel { + readonly textEditorModel: ITextModel; +} + export interface IWillMoveEvent { oldResource: URI; From 3f737ae1c76e2f61f298761ad48ccbf46cbd0b99 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 09:41:28 -0800 Subject: [PATCH 102/172] Strict null check textModelResolver --- src/tsconfig.strictNullChecks.json | 2 ++ .../common/textModelResolverService.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index ff390f15cb9..9a71de6256a 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -446,6 +446,8 @@ "./vs/workbench/services/textfile/common/textFileEditorModelManager.ts", "./vs/workbench/services/textfile/common/textfiles.ts", "./vs/workbench/services/textfile/node/textResourcePropertiesService.ts", + "./vs/workbench/services/textmodelResolver/common/textModelResolverService.ts", + "./vs/workbench/services/timer/electron-browser/timerService.ts", "./vs/workbench/services/title/common/titleService.ts", "./vs/workbench/services/untitled/common/untitledEditorService.ts", "./vs/workbench/services/viewlet/browser/viewlet.ts", diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index 1c6388a5929..1e281d53340 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -12,7 +12,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { ITextFileService, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import * as network from 'vs/base/common/network'; -import { ITextModelService, ITextModelContentProvider, ITextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, ITextModelContentProvider, ITextEditorModel, IActiveTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { IFileService } from 'vs/platform/files/common/files'; @@ -104,7 +104,7 @@ class ResourceModelCollection extends ReferenceCollection { const resource = URI.parse(key); const providers = this.providers[resource.scheme] || []; - const factories = providers.map(p => () => Promise.resolve(p.provideTextContent(resource))); + const factories = providers.map(p => () => Promise.resolve(p.provideTextContent(resource))); return first(factories).then(model => { if (!model) { @@ -130,15 +130,15 @@ export class TextModelResolverService implements ITextModelService { this.resourceModelCollection = instantiationService.createInstance(ResourceModelCollection); } - createModelReference(resource: URI): Promise> { + createModelReference(resource: URI): Promise> { return this._createModelReference(resource); } - private _createModelReference(resource: URI): Promise> { + private _createModelReference(resource: URI): Promise> { // Untitled Schema: go through cached input if (resource.scheme === network.Schemas.untitled) { - return this.untitledEditorService.loadOrCreate({ resource }).then(model => new ImmortalReference(model)); + return this.untitledEditorService.loadOrCreate({ resource }).then(model => new ImmortalReference(model as IActiveTextEditorModel)); } // InMemory Schema: go through model service cache @@ -149,7 +149,7 @@ export class TextModelResolverService implements ITextModelService { return Promise.reject(new Error('Cant resolve inmemory resource')); } - return Promise.resolve(new ImmortalReference(this.instantiationService.createInstance(ResourceEditorModel, resource))); + return Promise.resolve(new ImmortalReference(this.instantiationService.createInstance(ResourceEditorModel, resource) as IActiveTextEditorModel)); } const ref = this.resourceModelCollection.acquire(resource.toString()); From dd3996661505a0d6e593d0e69abf3a8ad6cf0cc0 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 09:53:08 -0800 Subject: [PATCH 103/172] Strict null check mainThreadHeapService --- package.json | 4 ++-- src/tsconfig.strictNullChecks.json | 1 + yarn.lock | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 606c1365c3b..3679da9592b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "dependencies": { "applicationinsights": "1.0.8", - "gc-signals": "^0.0.1", + "gc-signals": "^0.0.2", "getmac": "1.4.1", "graceful-fs": "4.1.11", "http-proxy-agent": "^2.1.0", @@ -150,4 +150,4 @@ "windows-mutex": "0.2.1", "windows-process-tree": "0.2.3" } -} +} \ No newline at end of file diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 9a71de6256a..2ab9b6ec0ca 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -56,6 +56,7 @@ "./vs/workbench/api/electron-browser/mainThreadErrors.ts", "./vs/workbench/api/electron-browser/mainThreadFileSystem.ts", "./vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts", + "./vs/workbench/api/electron-browser/mainThreadHeapService.ts", "./vs/workbench/api/electron-browser/mainThreadLanguages.ts", "./vs/workbench/api/electron-browser/mainThreadLogService.ts", "./vs/workbench/api/electron-browser/mainThreadMessageService.ts", diff --git a/yarn.lock b/yarn.lock index ee5b960a7e4..654114c0663 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3482,10 +3482,10 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gc-signals@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/gc-signals/-/gc-signals-0.0.1.tgz#91e3b7904168b58aa3dc78b619b7b4495b4038ab" - integrity sha1-keO3kEFotYqj3Hi2Gbe0SVtAOKs= +gc-signals@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/gc-signals/-/gc-signals-0.0.2.tgz#1cfa8a00adecaeeb93ea0dda72dad9e9f333e62f" + integrity sha512-Ghj4Co6x5bd3dvbAFuiDc6gN+BVK8ic8CBn70dXjzrtbC5hq4a+s4S6acEvftMP7LcQuHKN5v+30PGXhkCLoCQ== generate-function@^2.0.0: version "2.0.0" From 311a05ddf17a9ebe139b2df971324a598c9b8eb8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 09:56:27 -0800 Subject: [PATCH 104/172] Fix merge conflict with rename --- src/tsconfig.strictNullChecks.json | 2 +- .../common/textModelResolverService.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 2ab9b6ec0ca..4b60b2a69b2 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -32,7 +32,6 @@ "./vs/workbench/services/timer/**/*.ts" ], "files": [ - "./vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts", "./vs/monaco.d.ts", "./vs/nls.d.ts", "./vs/nls.mock.ts", @@ -64,6 +63,7 @@ "./vs/workbench/api/electron-browser/mainThreadProgress.ts", "./vs/workbench/api/electron-browser/mainThreadQuickOpen.ts", "./vs/workbench/api/electron-browser/mainThreadSCM.ts", + "./vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts", "./vs/workbench/api/electron-browser/mainThreadSearch.ts", "./vs/workbench/api/electron-browser/mainThreadStatusBar.ts", "./vs/workbench/api/electron-browser/mainThreadStorage.ts", diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index 1e281d53340..bc4a2084711 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -12,7 +12,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { ITextFileService, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import * as network from 'vs/base/common/network'; -import { ITextModelService, ITextModelContentProvider, ITextEditorModel, IActiveTextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, ITextModelContentProvider, ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { IFileService } from 'vs/platform/files/common/files'; @@ -130,15 +130,15 @@ export class TextModelResolverService implements ITextModelService { this.resourceModelCollection = instantiationService.createInstance(ResourceModelCollection); } - createModelReference(resource: URI): Promise> { + createModelReference(resource: URI): Promise> { return this._createModelReference(resource); } - private _createModelReference(resource: URI): Promise> { + private _createModelReference(resource: URI): Promise> { // Untitled Schema: go through cached input if (resource.scheme === network.Schemas.untitled) { - return this.untitledEditorService.loadOrCreate({ resource }).then(model => new ImmortalReference(model as IActiveTextEditorModel)); + return this.untitledEditorService.loadOrCreate({ resource }).then(model => new ImmortalReference(model as IResolvedTextEditorModel)); } // InMemory Schema: go through model service cache @@ -149,7 +149,7 @@ export class TextModelResolverService implements ITextModelService { return Promise.reject(new Error('Cant resolve inmemory resource')); } - return Promise.resolve(new ImmortalReference(this.instantiationService.createInstance(ResourceEditorModel, resource) as IActiveTextEditorModel)); + return Promise.resolve(new ImmortalReference(this.instantiationService.createInstance(ResourceEditorModel, resource) as IResolvedTextEditorModel)); } const ref = this.resourceModelCollection.acquire(resource.toString()); From 9fa249ae94d615d3318fbf1afb075accde129fc0 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 10:06:31 -0800 Subject: [PATCH 105/172] Strict null work on mainThreadSaveParticpants test --- .../mainThreadSaveParticipant.ts | 16 +++--- .../textfile/common/textFileEditorModel.ts | 4 +- .../services/textfile/common/textfiles.ts | 4 +- .../api/mainThreadSaveParticipant.test.ts | 52 +++++++++---------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 36490d0f2fe..f83e76de7a4 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -34,7 +34,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; -import { ISaveParticipant, SaveReason, IActiveTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; +import { ISaveParticipant, SaveReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../node/extHost.protocol'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -51,7 +51,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: IActiveTextFileEditorModel, 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); } @@ -113,7 +113,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(model: IActiveTextFileEditorModel, 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); } @@ -151,7 +151,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant // Nothing } - async participate(model: IActiveTextFileEditorModel, 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); } @@ -222,7 +222,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { // Nothing } - async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { const model = editorModel.textEditorModel; if (env.reason === SaveReason.AUTO @@ -293,7 +293,7 @@ class CodeActionOnSaveParticipant implements ISaveParticipant { @IConfigurationService private readonly _configurationService: IConfigurationService ) { } - async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { if (env.reason === SaveReason.AUTO) { return undefined; } @@ -373,7 +373,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant); } - async participate(editorModel: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise { + async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise { if (!shouldSynchronizeModel(editorModel.textEditorModel)) { // the model never made it to the extension @@ -424,7 +424,7 @@ export class SaveParticipant implements ISaveParticipant { this._saveParticipants.dispose(); } - async participate(model: IActiveTextFileEditorModel, 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/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 870f66a51f7..d056cc34156 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { isUndefinedOrNull } 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, IRawTextContent, ILoadOptions, LoadReason, IActiveTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions, LoadReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -661,7 +661,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil }; this.blockModelContentChange = true; - saveParticipantPromise = TextFileEditorModel.saveParticipant.participate(this as IActiveTextFileEditorModel, { reason: options.reason }).then(onCompleteOrError, onCompleteOrError); + saveParticipantPromise = TextFileEditorModel.saveParticipant.participate(this as IResolvedTextFileEditorModel, { reason: options.reason }).then(onCompleteOrError, onCompleteOrError); } // mark the save participant as current pending save operation diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index d9c897b069c..0e249fb61f7 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -29,7 +29,7 @@ export interface ISaveParticipant { /** * Participate in a save of a model. Allows to change the model before it is being saved to disk. */ - participate(model: IActiveTextFileEditorModel, env: { reason: SaveReason }): Promise; + participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise; } /** @@ -255,7 +255,7 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport isDisposed(): boolean; } -export interface IActiveTextFileEditorModel extends ITextFileEditorModel { +export interface IResolvedTextFileEditorModel extends ITextFileEditorModel { readonly textEditorModel: ITextModel; } diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts index 6fc405bc679..eb437ee4f29 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts @@ -13,7 +13,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; -import { ITextFileService, SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, SaveReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { snapshotToString } from 'vs/platform/files/common/files'; @@ -38,7 +38,7 @@ suite('MainThreadSaveParticipant', function () { }); test('insert final new line', async function () { - const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/final_new_line.txt'), 'utf8'); + const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/final_new_line.txt'), 'utf8') as IResolvedTextFileEditorModel; await model.load(); const configService = new TestConfigurationService(); @@ -47,66 +47,66 @@ suite('MainThreadSaveParticipant', function () { // No new line for empty lines let lineContent = ''; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // No new line if last line already empty - lineContent = `Hello New Line${model.textEditorModel!.getEOL()}`; - model.textEditorModel!.setValue(lineContent); + lineContent = `Hello New Line${model.textEditorModel.getEOL()}`; + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // New empty line added (single line) lineContent = 'Hello New Line'; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel!.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel.getEOL()}`); // New empty line added (multi line) - lineContent = `Hello New Line${model.textEditorModel!.getEOL()}Hello New Line${model.textEditorModel!.getEOL()}Hello New Line`; - model.textEditorModel!.setValue(lineContent); + lineContent = `Hello New Line${model.textEditorModel.getEOL()}Hello New Line${model.textEditorModel.getEOL()}Hello New Line`; + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel!.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()!), `${lineContent}${model.textEditorModel.getEOL()}`); }); test('trim final new lines', async function () { - const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8') as IResolvedTextFileEditorModel; await model.load(); const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); const participant = new TrimFinalNewLinesParticipant(configService, undefined!); const textContent = 'Trim New Line'; - const eol = `${model.textEditorModel!.getEOL()}`; + const eol = `${model.textEditorModel.getEOL()}`; // No new line removal if last line is not new line let lineContent = `${textContent}`; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // No new line removal if last line is single new line lineContent = `${textContent}${eol}`; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), lineContent); // Remove new line (single line with two new lines) lineContent = `${textContent}${eol}${eol}`; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); // Remove new lines (multiple lines with multiple new lines) lineContent = `${textContent}${eol}${textContent}${eol}${eol}${eol}`; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); await participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}${textContent}${eol}`); }); test('trim final new lines bug#39750', async function () { - const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8') as IResolvedTextFileEditorModel; await model.load(); const configService = new TestConfigurationService(); @@ -116,33 +116,33 @@ suite('MainThreadSaveParticipant', function () { // single line let lineContent = `${textContent}`; - model.textEditorModel!.setValue(lineContent); + model.textEditorModel.setValue(lineContent); // apply edits and push to undo stack. let textEdits = [{ range: new Range(1, 14, 1, 14), text: '.', forceMoveMarkers: false }]; - model.textEditorModel!.pushEditOperations([new Selection(1, 14, 1, 14)], textEdits, () => { return [new Selection(1, 15, 1, 15)]; }); + model.textEditorModel.pushEditOperations([new Selection(1, 14, 1, 14)], textEdits, () => { return [new Selection(1, 15, 1, 15)]; }); // undo - model.textEditorModel!.undo(); + model.textEditorModel.undo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}`); // trim final new lines should not mess the undo stack await participant.participate(model, { reason: SaveReason.EXPLICIT }); - model.textEditorModel!.redo(); + model.textEditorModel.redo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}.`); }); test('trim final new lines bug#46075', async function () { - const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8') as IResolvedTextFileEditorModel; await model.load(); const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); const participant = new TrimFinalNewLinesParticipant(configService, undefined!); const textContent = 'Test'; - const eol = `${model.textEditorModel!.getEOL()}`; + const eol = `${model.textEditorModel.getEOL()}`; let content = `${textContent}${eol}${eol}`; - model.textEditorModel!.setValue(content); + model.textEditorModel.setValue(content); // save many times for (let i = 0; i < 10; i++) { @@ -153,9 +153,9 @@ suite('MainThreadSaveParticipant', function () { assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); // undo should go back to previous content immediately - model.textEditorModel!.undo(); + model.textEditorModel.undo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}${eol}`); - model.textEditorModel!.redo(); + model.textEditorModel.redo(); assert.equal(snapshotToString(model.createSnapshot()!), `${textContent}${eol}`); }); }); From 3b451a68ba7a7c17747d6db000e1c83b130d0436 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 10:16:09 -0800 Subject: [PATCH 106/172] Fix strict null conflicts from making openEditor return Promise --- .../common/editor/diffEditorInput.ts | 2 +- .../preferences/browser/preferencesService.ts | 26 +++++++++---------- .../preferences/common/preferences.ts | 12 ++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/common/editor/diffEditorInput.ts b/src/vs/workbench/common/editor/diffEditorInput.ts index 44a8af3658a..ff410762774 100644 --- a/src/vs/workbench/common/editor/diffEditorInput.ts +++ b/src/vs/workbench/common/editor/diffEditorInput.ts @@ -18,7 +18,7 @@ export class DiffEditorInput extends SideBySideEditorInput { private cachedModel: DiffEditorModel | null; - constructor(name: string, description: string, original: EditorInput, modified: EditorInput, private forceOpenAsBinary?: boolean) { + constructor(name: string, description: string | null, original: EditorInput, modified: EditorInput, private forceOpenAsBinary?: boolean) { super(name, description, original, modified); } diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index 8efc41d7c34..7879f21bc17 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -171,15 +171,15 @@ export class PreferencesService extends Disposable implements IPreferencesServic return Promise.reject(`unknown resource: ${uri.toString()}`); } - openRawDefaultSettings(): Promise { + openRawDefaultSettings(): Promise { return this.editorService.openEditor({ resource: this.defaultSettingsRawResource }); } - openRawUserSettings(): Promise { + openRawUserSettings(): Promise { return this.editorService.openEditor({ resource: this.userSettingsResource }); } - openSettings(jsonEditor?: boolean): Promise { + openSettings(jsonEditor?: boolean): Promise { jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; @@ -200,7 +200,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic .then(() => this.editorGroupService.activeGroup.activeControl!); } - openGlobalSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + openGlobalSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; @@ -210,7 +210,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.openOrSwitchSettings2(ConfigurationTarget.USER, undefined, options, group); } - openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; @@ -225,7 +225,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.openOrSwitchSettings2(ConfigurationTarget.WORKSPACE, undefined, options, group); } - openFolderSettings(folder: URI, jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + openFolderSettings(folder: URI, jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { jsonEditor = typeof jsonEditor === 'undefined' ? this.configurationService.getValue('workbench.settings.editor') === 'json' : jsonEditor; @@ -282,7 +282,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.editorService.openEditor(this.instantiationService.createInstance(KeybindingsEditorInput), { pinned: true, revealIfOpened: true }).then(() => undefined); } - openDefaultKeybindingsFile(): Promise { + openDefaultKeybindingsFile(): Promise { return this.editorService.openEditor({ resource: this.defaultKeybindingsResource, label: nls.localize('defaultKeybindings', "Default Keybindings") }); } @@ -290,7 +290,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.openGlobalSettings(true) .then(editor => this.createPreferencesEditorModel(this.userSettingsResource) .then((settingsModel: IPreferencesEditorModel) => { - const codeEditor = getCodeEditor(editor.getControl()); + const codeEditor = editor ? getCodeEditor(editor.getControl()) : null; if (codeEditor) { this.addLanguageOverrideEntry(language, settingsModel, codeEditor) .then(position => { @@ -304,7 +304,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic })); } - private openOrSwitchSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group: IEditorGroup = this.editorGroupService.activeGroup): Promise { + private openOrSwitchSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group: IEditorGroup = this.editorGroupService.activeGroup): Promise { const editorInput = this.getActiveSettingsEditorInput(group); if (editorInput) { const editorInputResource = editorInput.master.getResource(); @@ -315,11 +315,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.doOpenSettings(configurationTarget, resource, options, group); } - private openOrSwitchSettings2(configurationTarget: ConfigurationTarget, folderUri?: URI, options?: ISettingsEditorOptions, group: IEditorGroup = this.editorGroupService.activeGroup): Promise { + private openOrSwitchSettings2(configurationTarget: ConfigurationTarget, folderUri?: URI, options?: ISettingsEditorOptions, group: IEditorGroup = this.editorGroupService.activeGroup): Promise { return this.doOpenSettings2(configurationTarget, folderUri, options, group); } - private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { const openSplitJSON = !!this.configurationService.getValue(USE_SPLIT_JSON_SETTING); if (openSplitJSON) { return this.doOpenSplitJSON(configurationTarget, resource, options, group); @@ -348,7 +348,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } - private doOpenSplitJSON(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { + private doOpenSplitJSON(configurationTarget: ConfigurationTarget, resource: URI, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise { return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) .then(editableSettingsEditorInput => { if (!options) { @@ -368,7 +368,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.instantiationService.createInstance(Settings2EditorModel, this.getDefaultSettings(ConfigurationTarget.USER)); } - private doOpenSettings2(target: ConfigurationTarget, folderUri: URI | undefined, options?: IEditorOptions, group?: IEditorGroup): Promise { + private doOpenSettings2(target: ConfigurationTarget, folderUri: URI | undefined, options?: IEditorOptions, group?: IEditorGroup): Promise { const input = this.settingsEditor2Input; const settingsOptions: ISettingsEditorOptions = { ...options, diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index b1d1d0a4a99..7dc27694012 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -198,14 +198,14 @@ export interface IPreferencesService { createPreferencesEditorModel(uri: URI): Promise>; createSettings2EditorModel(): Settings2EditorModel; // TODO - openRawDefaultSettings(): Promise; - openSettings(jsonEditor?: boolean): Promise; - openGlobalSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; - openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; - openFolderSettings(folder: URI, jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; + openRawDefaultSettings(): Promise; + openSettings(jsonEditor?: boolean): Promise; + openGlobalSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; + openWorkspaceSettings(jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; + openFolderSettings(folder: URI, jsonEditor?: boolean, options?: ISettingsEditorOptions, group?: IEditorGroup): Promise; switchSettings(target: ConfigurationTarget, resource: URI, jsonEditor?: boolean): Promise; openGlobalKeybindingSettings(textual: boolean): Promise; - openDefaultKeybindingsFile(): Promise; + openDefaultKeybindingsFile(): Promise; configureSettingsForLanguage(language: string): void; } From 928947812732d1f08a39abbf06282d2a3439293a Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 5 Mar 2019 18:43:51 +0000 Subject: [PATCH 107/172] Interpret NO_PROXY (#68260) --- .../services/extensions/node/proxyResolver.ts | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/extensions/node/proxyResolver.ts b/src/vs/workbench/services/extensions/node/proxyResolver.ts index 98fed1fac42..1643badcc71 100644 --- a/src/vs/workbench/services/extensions/node/proxyResolver.ts +++ b/src/vs/workbench/services/extensions/node/proxyResolver.ts @@ -8,6 +8,7 @@ import * as https from 'https'; import * as nodeurl from 'url'; import { assign } from 'vs/base/common/objects'; +import { endsWith } from 'vs/base/common/strings'; import { IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration'; import { ProxyAgent } from 'vscode-proxy-agent'; @@ -44,15 +45,18 @@ function setupProxyResolution( extHostLogService: ExtHostLogService, mainThreadTelemetry: MainThreadTelemetryShape ) { + const env = process.env; + let settingsProxy = proxyFromConfigURL(configProvider.getConfiguration('http') .get('proxy')); configProvider.onDidChangeConfiguration(e => { settingsProxy = proxyFromConfigURL(configProvider.getConfiguration('http') .get('proxy')); }); - const env = process.env; let envProxy = proxyFromConfigURL(env.https_proxy || env.HTTPS_PROXY || env.http_proxy || env.HTTP_PROXY); // Not standardized. + let envNoProxy = noProxyFromEnv(env.no_proxy || env.NO_PROXY); // Not standardized. + let cacheRolls = 0; let oldCache = new Map(); let cache = new Map(); @@ -90,6 +94,7 @@ function setupProxyResolution( let envCount = 0; let settingsCount = 0; let localhostCount = 0; + let envNoProxyCount = 0; let results: ConnectionResult[] = []; function logEvent() { timeout = undefined; @@ -104,11 +109,12 @@ function setupProxyResolution( "envCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "settingsCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "localhostCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "envNoProxyCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "results": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } } */ - mainThreadTelemetry.$publicLog('resolveProxy', { count, duration, errorCount, cacheCount, cacheSize: cache.size, cacheRolls, envCount, settingsCount, localhostCount, results }); - count = duration = errorCount = cacheCount = envCount = settingsCount = localhostCount = 0; + mainThreadTelemetry.$publicLog('resolveProxy', { count, duration, errorCount, cacheCount, cacheSize: cache.size, cacheRolls, envCount, settingsCount, localhostCount, envNoProxyCount, results }); + count = duration = errorCount = cacheCount = envCount = settingsCount = localhostCount = envNoProxyCount = 0; results = []; } @@ -127,6 +133,13 @@ function setupProxyResolution( return; } + if (envNoProxy(hostname, String(parsedUrl.port || (opts.agent).defaultPort))) { + envNoProxyCount++; + callback('DIRECT'); + extHostLogService.trace('ProxyResolver#resolveProxy envNoProxy', url, 'DIRECT'); + return; + } + if (settingsProxy) { settingsCount++; callback(settingsProxy); @@ -214,6 +227,32 @@ function proxyFromConfigURL(configURL: string | undefined) { return undefined; } +function noProxyFromEnv(envValue?: string) { + const value = (envValue || '') + .trim() + .toLowerCase(); + + if (value === '*') { + return () => true; + } + + const filters = value + .split(',') + .map(s => s.trim().split(':', 2)) + .map(([name, port]) => ({ name, port })) + .filter(filter => !!filter.name) + .map(({ name, port }) => { + const domain = name[0] === '.' ? name : `.${name}`; + return { domain, port }; + }); + if (!filters.length) { + return () => false; + } + return (hostname: string, port: string) => filters.some(({ domain, port: filterPort }) => { + return endsWith(`.${hostname.toLowerCase()}`, domain) && (!filterPort || port === filterPort); + }); +} + function createPatchedModules(configProvider: ExtHostConfigProvider, resolveProxy: ReturnType) { const setting = { config: configProvider.getConfiguration('http') From 81b713fe6bb9a6c368f3601df31d7be83c15fd1b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 10:34:30 -0800 Subject: [PATCH 108/172] Strict null work in extensionEditor --- src/tsconfig.strictNullChecks.json | 18 +++++++++++++++-- .../electron-browser/extensionEditor.ts | 16 +++++++++------ .../extensions.contribution.ts | 4 ++-- .../extensionsAutoProfiler.ts | 2 +- .../electron-browser/extensionsViewlet.ts | 2 +- .../electron-browser/extensionsViews.ts | 12 ++++++++--- .../runtimeExtensionsEditor.ts | 20 +++++++++---------- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 4b60b2a69b2..beef6f1b918 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -67,6 +67,7 @@ "./vs/workbench/api/electron-browser/mainThreadSearch.ts", "./vs/workbench/api/electron-browser/mainThreadStatusBar.ts", "./vs/workbench/api/electron-browser/mainThreadStorage.ts", + "./vs/workbench/api/electron-browser/mainThreadTask.ts", "./vs/workbench/api/electron-browser/mainThreadTelemetry.ts", "./vs/workbench/api/electron-browser/mainThreadTerminalService.ts", "./vs/workbench/api/electron-browser/mainThreadTreeViews.ts", @@ -146,6 +147,7 @@ "./vs/workbench/browser/parts/sidebar/sidebarPart.ts", "./vs/workbench/browser/parts/statusbar/statusbar.ts", "./vs/workbench/browser/parts/statusbar/statusbarPart.ts", + "./vs/workbench/browser/parts/titlebar/menubarControl.ts", "./vs/workbench/browser/parts/views/customView.ts", "./vs/workbench/browser/parts/views/panelViewlet.ts", "./vs/workbench/browser/parts/views/views.ts", @@ -236,11 +238,14 @@ "./vs/workbench/contrib/extensions/common/extensionsFileTemplate.ts", "./vs/workbench/contrib/extensions/common/extensionsInput.ts", "./vs/workbench/contrib/extensions/common/extensionsUtils.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActivationProgress.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsList.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsWidgets.ts", + "./vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts", "./vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput.ts", "./vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts", "./vs/workbench/contrib/extensions/test/common/extensionQuery.test.ts", @@ -281,7 +286,9 @@ "./vs/workbench/contrib/output/electron-browser/output.contribution.ts", "./vs/workbench/contrib/output/electron-browser/outputServices.ts", "./vs/workbench/contrib/output/node/outputAppender.ts", + "./vs/workbench/contrib/preferences/browser/settingsLayout.ts", "./vs/workbench/contrib/preferences/browser/settingsWidgets.ts", + "./vs/workbench/contrib/preferences/common/preferences.ts", "./vs/workbench/contrib/preferences/common/smartSnippetInserter.ts", "./vs/workbench/contrib/preferences/test/common/smartSnippetInserter.test.ts", "./vs/workbench/contrib/quickopen/browser/commandsHandler.ts", @@ -291,12 +298,12 @@ "./vs/workbench/contrib/quickopen/browser/quickopen.contribution.ts", "./vs/workbench/contrib/quickopen/browser/viewPickerHandler.ts", "./vs/workbench/contrib/relauncher/electron-browser/relauncher.contribution.ts", - "./vs/workbench/contrib/scm/common/scm.ts", - "./vs/workbench/contrib/scm/common/scmService.ts", "./vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts", "./vs/workbench/contrib/scm/browser/scmActivity.ts", "./vs/workbench/contrib/scm/browser/scmMenus.ts", "./vs/workbench/contrib/scm/browser/scmUtil.ts", + "./vs/workbench/contrib/scm/common/scm.ts", + "./vs/workbench/contrib/scm/common/scmService.ts", "./vs/workbench/contrib/search/browser/openAnythingHandler.ts", "./vs/workbench/contrib/search/browser/openFileHandler.ts", "./vs/workbench/contrib/search/browser/openSymbolHandler.ts", @@ -318,6 +325,9 @@ "./vs/workbench/contrib/stats/test/workspaceStats.test.ts", "./vs/workbench/contrib/surveys/electron-browser/languageSurveys.contribution.ts", "./vs/workbench/contrib/surveys/electron-browser/nps.contribution.ts", + "./vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts", + "./vs/workbench/contrib/terminal/browser/terminal.contribution.ts", + "./vs/workbench/contrib/terminal/browser/terminal.ts", "./vs/workbench/contrib/terminal/browser/terminalActions.ts", "./vs/workbench/contrib/terminal/browser/terminalCommandTracker.ts", "./vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts", @@ -327,6 +337,7 @@ "./vs/workbench/contrib/terminal/browser/terminalPanel.ts", "./vs/workbench/contrib/terminal/browser/terminalProcessManager.ts", "./vs/workbench/contrib/terminal/browser/terminalQuickOpen.ts", + "./vs/workbench/contrib/terminal/browser/terminalService.ts", "./vs/workbench/contrib/terminal/browser/terminalTab.ts", "./vs/workbench/contrib/terminal/browser/terminalWidgetManager.ts", "./vs/workbench/contrib/terminal/common/terminal.ts", @@ -336,6 +347,9 @@ "./vs/workbench/contrib/terminal/common/terminalMenu.ts", "./vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts", "./vs/workbench/contrib/terminal/common/terminalService.ts", + "./vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts", + "./vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts", + "./vs/workbench/contrib/terminal/electron-browser/terminalService.ts", "./vs/workbench/contrib/terminal/node/terminal.ts", "./vs/workbench/contrib/terminal/node/terminalProcess.ts", "./vs/workbench/contrib/terminal/node/windowsShellHelper.ts", diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts index 54f6af6c0d4..cee2fd121d7 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts @@ -89,8 +89,8 @@ function removeEmbeddedSVGs(documentContent: string): string { class NavBar { - private _onChange = new Emitter<{ id: string, focus: boolean }>(); - get onChange(): Event<{ id: string, focus: boolean }> { return this._onChange.event; } + private _onChange = new Emitter<{ id: string | null, focus: boolean }>(); + get onChange(): Event<{ id: string | null, focus: boolean }> { return this._onChange.event; } private currentId: string | null = null; private actions: Action[]; @@ -564,17 +564,21 @@ export class ExtensionEditor extends BaseEditor { } private openReadme(): Promise { - return this.openMarkdown(this.extensionReadme.get(), localize('noReadme', "No README available.")); + return this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available.")); } private openChangelog(): Promise { - return this.openMarkdown(this.extensionChangelog.get(), localize('noChangelog', "No Changelog available.")); + return this.openMarkdown(this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available.")); } private openContributions(): Promise { const content = $('div', { class: 'subcontent', tabindex: '0' }); - return this.loadContents(() => this.extensionManifest.get()) + return this.loadContents(() => this.extensionManifest!.get()) .then(manifest => { + if (!manifest) { + return content; + } + const scrollableContent = new DomScrollableElement(content, {}); const layout = () => scrollableContent.scanDomNode(); @@ -619,7 +623,7 @@ export class ExtensionEditor extends BaseEditor { return Promise.resolve(this.content); } - return this.loadContents(() => this.extensionDependencies.get()) + return this.loadContents(() => this.extensionDependencies!.get()) .then(extensionDependencies => { if (extensionDependencies) { const content = $('div', { class: 'subcontent' }); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 9611f624c74..689e0509b46 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -70,7 +70,7 @@ Registry.as(Extensions.Quickopen).registerQuickOpenHandler( ExtensionsHandler, ExtensionsHandler.ID, 'ext ', - null, + undefined, localize('extensionsCommands', "Manage Extensions"), true ) @@ -81,7 +81,7 @@ Registry.as(Extensions.Quickopen).registerQuickOpenHandler( GalleryExtensionsHandler, GalleryExtensionsHandler.ID, 'ext install ', - null, + undefined, localize('galleryExtensionsCommands', "Install Gallery Extensions"), true ) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts index 5fb573a33a3..154964ca211 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts @@ -49,7 +49,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont if (event.isResponsive && this._session.has(target)) { // stop profiling when responsive again - this._session.get(target).cancel(); + this._session.get(target)!.cancel(); } else if (!event.isResponsive && !this._session.has(target)) { // start profiling if not yet profiling diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts index d3dfeb19447..1a2d50168ba 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts @@ -275,7 +275,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio private searchBox: SuggestEnabledInput; private extensionsBox: HTMLElement; private primaryActions: IAction[]; - private secondaryActions: IAction[]; + private secondaryActions: IAction[] | null; private disposables: IDisposable[] = []; private searchViewletState: object; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts index 51177b7ca33..696f13d9b52 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts @@ -68,7 +68,7 @@ export class ExtensionsListView extends ViewletPanel { private extensionsList: HTMLElement; private badge: CountBadge; protected badgeContainer: HTMLElement; - private list: WorkbenchPagedList; + private list: WorkbenchPagedList | null; constructor( private options: IViewletViewOptions, @@ -133,7 +133,9 @@ export class ExtensionsListView extends ViewletPanel { protected layoutBody(height: number, width: number): void { this.extensionsList.style.height = height + 'px'; - this.list.layout(height, width); + if (this.list) { + this.list.layout(height, width); + } } async show(query: string): Promise> { @@ -168,7 +170,7 @@ export class ExtensionsListView extends ViewletPanel { } count(): number { - return this.list.length; + return this.list ? this.list.length : 0; } protected showEmptyModel(): Promise> { @@ -728,6 +730,10 @@ export class ExtensionsListView extends ViewletPanel { focus(): void { super.focus(); + if (!this.list) { + return; + } + if (!(this.list.getFocus().length || this.list.getSelection().length)) { this.list.focusNext(); } diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 6bfbb3da3c9..da6880ff9b7 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -100,7 +100,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { public static readonly ID: string = 'workbench.editor.runtimeExtensions'; private _list: WorkbenchList | null; - private _profileInfo: IExtensionHostProfile; + private _profileInfo: IExtensionHostProfile | null; private _elements: IRuntimeExtension[] | null; private _extensionsDescriptions: IExtensionDescription[]; @@ -385,7 +385,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { } } - if (this._profileInfo) { + if (this._profileInfo && element.profileInfo) { data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`; } else { data.profileTime.textContent = ''; @@ -471,18 +471,18 @@ export class ReportExtensionIssueAction extends Action { private static _label = nls.localize('reportExtensionIssue', "Report Issue"); private readonly _url: string; - private readonly _task: () => Promise; + private readonly _task?: () => Promise; constructor(extension: { description: IExtensionDescription; marketplaceInfo: IExtension; - status: IExtensionsStatus; + status?: IExtensionsStatus; unresponsiveProfile?: IExtensionHostProfile }) { super(ReportExtensionIssueAction._id, ReportExtensionIssueAction._label, 'extension-action report-issue'); this.enabled = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User - && Boolean(extension.description.repository) && Boolean(extension.description.repository.url); + && !!extension.description.repository && !!extension.description.repository.url; const { url, task } = ReportExtensionIssueAction._generateNewIssueUrl(extension); this._url = url; @@ -499,11 +499,11 @@ export class ReportExtensionIssueAction extends Action { private static _generateNewIssueUrl(extension: { description: IExtensionDescription; marketplaceInfo: IExtension; - status: IExtensionsStatus; + status?: IExtensionsStatus; unresponsiveProfile?: IExtensionHostProfile }): { url: string, task?: () => Promise } { - let task: () => Promise | undefined; + let task: (() => Promise) | undefined; let baseUrl = extension.marketplaceInfo && extension.marketplaceInfo.type === ExtensionType.User && extension.description.repository ? extension.description.repository.url : undefined; if (!!baseUrl) { baseUrl = `${baseUrl.indexOf('.git') !== -1 ? baseUrl.substr(0, baseUrl.length - 4) : baseUrl}/issues/new/`; @@ -521,7 +521,7 @@ export class ReportExtensionIssueAction extends Action { let path = join(os.homedir(), `${extension.description.identifier.value}-unresponsive.cpuprofile.txt`); task = async () => { const profiler = await import('v8-inspect-profiler'); - const data = profiler.rewriteAbsolutePaths({ profile: extension.unresponsiveProfile.data }, 'pii_removed'); + const data = profiler.rewriteAbsolutePaths({ profile: extension.unresponsiveProfile!.data }, 'pii_removed'); profiler.writeProfile(data, path).then(undefined, onUnexpectedError); }; message = `:warning: Make sure to **attach** this file from your *home*-directory: \`${path}\` :warning:\n\nFind more details here: https://github.com/Microsoft/vscode/wiki/Explain:-extension-causes-high-cpu-load`; @@ -661,7 +661,7 @@ export class SaveExtensionHostProfileAction extends Action { } const profileInfo = this._extensionHostProfileService.lastProfile; - let dataToWrite: object = profileInfo.data; + let dataToWrite: object = profileInfo ? profileInfo.data : {}; if (this._environmentService.isBuilt) { const profiler = await import('v8-inspect-profiler'); @@ -676,6 +676,6 @@ export class SaveExtensionHostProfileAction extends Action { picked = picked + '.txt'; } - return writeFile(picked, JSON.stringify(profileInfo.data, null, '\t')); + return writeFile(picked, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t')); } } From bde0b864004a602fccf127308530de224e65a168 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 10:53:43 -0800 Subject: [PATCH 109/172] Strict null work in contrib/preferences --- src/tsconfig.strictNullChecks.json | 7 +++- .../editor/common/services/resolverService.ts | 2 +- .../common/jsonContributionRegistry.ts | 2 +- .../preferences/browser/preferencesActions.ts | 4 ++- .../preferences/browser/preferencesWidgets.ts | 33 ++++++++++++------- .../contrib/preferences/common/preferences.ts | 4 +-- .../common/preferencesContribution.ts | 6 ++-- .../electron-browser/preferencesSearch.ts | 14 ++++---- .../services/editor/common/editorService.ts | 2 +- .../preferences/common/preferences.ts | 12 +++---- .../preferences/common/preferencesModels.ts | 4 ++- 11 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index beef6f1b918..5e51fd727b6 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -67,7 +67,6 @@ "./vs/workbench/api/electron-browser/mainThreadSearch.ts", "./vs/workbench/api/electron-browser/mainThreadStatusBar.ts", "./vs/workbench/api/electron-browser/mainThreadStorage.ts", - "./vs/workbench/api/electron-browser/mainThreadTask.ts", "./vs/workbench/api/electron-browser/mainThreadTelemetry.ts", "./vs/workbench/api/electron-browser/mainThreadTerminalService.ts", "./vs/workbench/api/electron-browser/mainThreadTreeViews.ts", @@ -244,6 +243,8 @@ "./vs/workbench/contrib/extensions/electron-browser/extensionsActivationProgress.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsList.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensionsViews.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsWidgets.ts", "./vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts", "./vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput.ts", @@ -286,10 +287,14 @@ "./vs/workbench/contrib/output/electron-browser/output.contribution.ts", "./vs/workbench/contrib/output/electron-browser/outputServices.ts", "./vs/workbench/contrib/output/node/outputAppender.ts", + "./vs/workbench/contrib/preferences/browser/preferencesActions.ts", + "./vs/workbench/contrib/preferences/browser/preferencesWidgets.ts", "./vs/workbench/contrib/preferences/browser/settingsLayout.ts", "./vs/workbench/contrib/preferences/browser/settingsWidgets.ts", "./vs/workbench/contrib/preferences/common/preferences.ts", + "./vs/workbench/contrib/preferences/common/preferencesContribution.ts", "./vs/workbench/contrib/preferences/common/smartSnippetInserter.ts", + "./vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts", "./vs/workbench/contrib/preferences/test/common/smartSnippetInserter.test.ts", "./vs/workbench/contrib/quickopen/browser/commandsHandler.ts", "./vs/workbench/contrib/quickopen/browser/gotoLineHandler.ts", diff --git a/src/vs/editor/common/services/resolverService.ts b/src/vs/editor/common/services/resolverService.ts index ef65b34685e..d87baf65a43 100644 --- a/src/vs/editor/common/services/resolverService.ts +++ b/src/vs/editor/common/services/resolverService.ts @@ -36,7 +36,7 @@ export interface ITextModelContentProvider { /** * Given a resource, return the content of the resource as `ITextModel`. */ - provideTextContent(resource: URI): Promise | null; + provideTextContent(resource: URI): Promise | null | undefined; } export interface ITextEditorModel extends IEditorModel { diff --git a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts index 3206c7ba3de..972566d2b48 100644 --- a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts +++ b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts @@ -12,7 +12,7 @@ export const Extensions = { }; export interface ISchemaContributions { - schemas?: { [id: string]: IJSONSchema }; + schemas: { [id: string]: IJSONSchema }; } export interface IJSONContributionRegistry { diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts index 0a52f70fb78..fd8600260b5 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesActions.ts @@ -260,7 +260,9 @@ export class ConfigureLanguageBasedSettingsAction extends Action { .then(pick => { if (pick) { const modeId = this.modeService.getModeIdForLanguageName(pick.label.toLowerCase()); - return this.preferencesService.configureSettingsForLanguage(modeId); + if (typeof modeId === 'string') { + return this.preferencesService.configureSettingsForLanguage(modeId); + } } return undefined; }); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index 04a1058cd26..55c8f055069 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -226,13 +226,17 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { if (this.settingsGroup.range.startLineNumber - 3 !== 1) { this.editor.focus(); const lineNumber = this.settingsGroup.range.startLineNumber - 2; - this.editor.setPosition({ lineNumber, column: this.editor.getModel().getLineMinColumn(lineNumber) }); + if (this.editor.hasModel()) { + this.editor.setPosition({ lineNumber, column: this.editor.getModel().getLineMinColumn(lineNumber) }); + } } break; case KeyCode.DownArrow: const lineNumber = this.isCollapsed() ? this.settingsGroup.range.startLineNumber : this.settingsGroup.range.startLineNumber - 1; this.editor.focus(); - this.editor.setPosition({ lineNumber, column: this.editor.getModel().getLineMinColumn(lineNumber) }); + if (this.editor.hasModel()) { + this.editor.setPosition({ lineNumber, column: this.editor.getModel().getLineMinColumn(lineNumber) }); + } break; } } @@ -286,7 +290,7 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { export class FolderSettingsActionItem extends BaseActionItem { - private _folder: IWorkspaceFolder; + private _folder: IWorkspaceFolder | null; private _folderSettingCounts = new Map(); private container: HTMLElement; @@ -308,17 +312,21 @@ export class FolderSettingsActionItem extends BaseActionItem { this.disposables.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onWorkspaceFoldersChanged())); } - get folder(): IWorkspaceFolder { + get folder(): IWorkspaceFolder | null { return this._folder; } - set folder(folder: IWorkspaceFolder) { + set folder(folder: IWorkspaceFolder | null) { this._folder = folder; this.update(); } setCount(settingsTarget: URI, count: number): void { - const folder = this.contextService.getWorkspaceFolder(settingsTarget).uri; + const workspaceFolder = this.contextService.getWorkspaceFolder(settingsTarget); + if (!workspaceFolder) { + throw new Error('unknown folder'); + } + const folder = workspaceFolder.uri; this._folderSettingCounts.set(folder.toString(), count); this.update(); } @@ -374,8 +382,8 @@ export class FolderSettingsActionItem extends BaseActionItem { private onWorkspaceFoldersChanged(): void { const oldFolder = this._folder; const workspace = this.contextService.getWorkspace(); - if (this._folder) { - this._folder = workspace.folders.filter(folder => folder.uri.toString() === this._folder.uri.toString())[0] || workspace.folders[0]; + if (oldFolder) { + this._folder = workspace.folders.filter(folder => folder.uri.toString() === oldFolder.uri.toString())[0] || workspace.folders[0]; } this._folder = this._folder ? this._folder : workspace.folders.length === 1 ? workspace.folders[0] : null; @@ -384,7 +392,7 @@ export class FolderSettingsActionItem extends BaseActionItem { if (this._action.checked) { if ((oldFolder || !this._folder) || (!oldFolder || this._folder) - || (oldFolder && this._folder && oldFolder.uri.toString() === this._folder.uri.toString())) { + || (oldFolder && this._folder && (oldFolder as IWorkspaceFolder).uri.toString() === (this._folder as IWorkspaceFolder).uri.toString())) { this._action.run(this._folder); } } @@ -625,9 +633,10 @@ export class SearchWidget extends Widget { const focusTracker = this._register(DOM.trackFocus(this.inputBox.inputElement)); this._register(focusTracker.onDidFocus(() => this._onFocus.fire())); - if (this.options.focusKey) { - this._register(focusTracker.onDidFocus(() => this.options.focusKey.set(true))); - this._register(focusTracker.onDidBlur(() => this.options.focusKey.set(false))); + const focusKey = this.options.focusKey; + if (focusKey) { + this._register(focusTracker.onDidFocus(() => focusKey.set(true))); + this._register(focusTracker.onDidBlur(() => focusKey.set(false))); } } diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index 26985c7b847..bdc2c48a344 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -36,11 +36,11 @@ export interface IPreferencesSearchService { _serviceBrand: any; getLocalSearchProvider(filter: string): ISearchProvider; - getRemoteSearchProvider(filter: string, newExtensionsOnly?: boolean): ISearchProvider; + getRemoteSearchProvider(filter: string, newExtensionsOnly?: boolean): ISearchProvider | undefined; } export interface ISearchProvider { - searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken): Promise; + searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken): Promise; } export interface IKeybindingsEditor extends IEditor { diff --git a/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts b/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts index c1a65046bc1..4fe4d12d136 100644 --- a/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts @@ -61,7 +61,7 @@ export class PreferencesContribution implements IWorkbenchContribution { } } - private onEditorOpening(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions, group: IEditorGroup): IOpenEditorOverride { + private onEditorOpening(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined { const resource = editor.getResource(); if ( !resource || @@ -108,7 +108,7 @@ export class PreferencesContribution implements IWorkbenchContribution { private start(): void { this.textModelResolverService.registerTextModelContentProvider('vscode', { - provideTextContent: (uri: URI): Promise => { + provideTextContent: (uri: URI): Promise | null => { if (uri.scheme !== 'vscode') { return null; } @@ -123,7 +123,7 @@ export class PreferencesContribution implements IWorkbenchContribution { }); } - private getSchemaModel(uri: URI): ITextModel { + private getSchemaModel(uri: URI): ITextModel | null { let schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()]; if (schema) { const modelContent = JSON.stringify(schema); diff --git a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts index c72c3d6c1ee..e01930681bd 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts @@ -26,7 +26,7 @@ import { nullRange } from 'vs/workbench/services/preferences/common/preferencesM import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export interface IEndpointDetails { - urlBase: string; + urlBase?: string; key?: string; } @@ -77,14 +77,14 @@ export class PreferencesSearchService extends Disposable implements IPreferences } } - getRemoteSearchProvider(filter: string, newExtensionsOnly = false): ISearchProvider { + getRemoteSearchProvider(filter: string, newExtensionsOnly = false): ISearchProvider | undefined { const opts: IRemoteSearchProviderOptions = { filter, newExtensionsOnly, endpoint: this._endpoint }; - return this.remoteSearchAllowed && this.instantiationService.createInstance(RemoteSearchProvider, opts, this._installedExtensions); + return this.remoteSearchAllowed ? this.instantiationService.createInstance(RemoteSearchProvider, opts, this._installedExtensions) : undefined; } getLocalSearchProvider(filter: string): LocalSearchProvider { @@ -165,7 +165,7 @@ class RemoteSearchProvider implements ISearchProvider { private static readonly MAX_REQUESTS = 10; private static readonly NEW_EXTENSIONS_MIN_SCORE = 1; - private _remoteSearchP: Promise; + private _remoteSearchP: Promise; constructor(private options: IRemoteSearchProviderOptions, private installedExtensions: Promise, @IEnvironmentService private readonly environmentService: IEnvironmentService, @@ -177,8 +177,8 @@ class RemoteSearchProvider implements ISearchProvider { Promise.resolve(null); } - searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken): Promise { - return this._remoteSearchP.then(remoteResult => { + searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken): Promise { + return this._remoteSearchP.then((remoteResult) => { if (!remoteResult) { return null; } @@ -278,7 +278,7 @@ class RemoteSearchProvider implements ISearchProvider { headers, timeout: 5000 }, CancellationToken.None).then(context => { - if (context.res.statusCode >= 300) { + if (typeof context.res.statusCode === 'number' && context.res.statusCode >= 300) { throw new Error(`${JSON.stringify(details)} returned status code: ${context.res.statusCode}`); } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index e47ffb540bf..a0f2e0006a1 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -36,7 +36,7 @@ export interface IOpenEditorOverride { * If defined, will prevent the opening of an editor and replace the resulting * promise with the provided promise for the openEditor() call. */ - override?: Promise; + override?: Promise; } export interface IActiveEditor extends IEditor { diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 7dc27694012..06b0a00d28e 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -69,8 +69,8 @@ export interface ISetting { } export interface IExtensionSetting extends ISetting { - extensionName: string; - extensionPublisher: string; + extensionName?: string; + extensionPublisher?: string; } export interface ISearchResult { @@ -97,7 +97,7 @@ export interface IFilterResult { export interface ISettingMatch { setting: ISetting; - matches: IRange[]; + matches: IRange[] | null; score: number; } @@ -136,8 +136,8 @@ export interface IPreferencesEditorModel { dispose(): void; } -export type IGroupFilter = (group: ISettingsGroup) => boolean; -export type ISettingMatcher = (setting: ISetting, group: ISettingsGroup) => { matches: IRange[], score: number }; +export type IGroupFilter = (group: ISettingsGroup) => boolean | null; +export type ISettingMatcher = (setting: ISetting, group: ISettingsGroup) => { matches: IRange[], score: number } | null; export interface ISettingsEditorModel extends IPreferencesEditorModel { readonly onDidChangeGroups: Event; @@ -207,7 +207,7 @@ export interface IPreferencesService { openGlobalKeybindingSettings(textual: boolean): Promise; openDefaultKeybindingsFile(): Promise; - configureSettingsForLanguage(language: string): void; + configureSettingsForLanguage(language: string | null): void; } export function getSettingsTargetName(target: ConfigurationTarget, resource: URI, workspaceContextService: IWorkspaceContextService): string { diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index 1c7936e9096..e49a53b39c8 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -178,7 +178,9 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti resultGroups.forEach(group => { group.result.filterMatches.forEach(filterMatch => { filteredSettings.push(filterMatch.setting); - matches.push(...filterMatch.matches); + if (filterMatch.matches) { + matches.push(...filterMatch.matches); + } }); }); From 39e7e1f339d50896d08a29b5b1a749d71e924ed1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 11:08:41 -0800 Subject: [PATCH 110/172] Strict null work on markers panel --- src/tsconfig.strictNullChecks.json | 3 +++ .../contrib/markers/browser/markersPanel.ts | 13 +++++++------ .../contrib/markers/browser/markersTreeViewer.ts | 12 ++++++------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 5e51fd727b6..45b6c97b069 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -271,11 +271,14 @@ "./vs/workbench/contrib/logs/common/logs.contribution.ts", "./vs/workbench/contrib/logs/common/logsActions.ts", "./vs/workbench/contrib/markers/browser/constants.ts", + "./vs/workbench/contrib/markers/browser/markers.contribution.ts", "./vs/workbench/contrib/markers/browser/markers.ts", "./vs/workbench/contrib/markers/browser/markersFileDecorations.ts", "./vs/workbench/contrib/markers/browser/markersFilterOptions.ts", "./vs/workbench/contrib/markers/browser/markersModel.ts", + "./vs/workbench/contrib/markers/browser/markersPanel.ts", "./vs/workbench/contrib/markers/browser/markersPanelActions.ts", + "./vs/workbench/contrib/markers/browser/markersTreeViewer.ts", "./vs/workbench/contrib/markers/browser/messages.ts", "./vs/workbench/contrib/markers/test/electron-browser/markersModel.test.ts", "./vs/workbench/contrib/output/browser/logViewer.ts", diff --git a/src/vs/workbench/contrib/markers/browser/markersPanel.ts b/src/vs/workbench/contrib/markers/browser/markersPanel.ts index 435e6ed6500..3c7a8de1582 100644 --- a/src/vs/workbench/contrib/markers/browser/markersPanel.ts +++ b/src/vs/workbench/contrib/markers/browser/markersPanel.ts @@ -187,7 +187,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { public openFileAtElement(element: any, preserveFocus: boolean, sideByside: boolean, pinned: boolean): boolean { const { resource, selection, event, data } = element instanceof Marker ? { resource: element.resource, selection: element.range, event: 'problems.selectDiagnostic', data: this.getTelemetryData(element.marker) } : element instanceof RelatedInformation ? { resource: element.raw.resource, selection: element.raw, event: 'problems.selectRelatedInformation', data: this.getTelemetryData(element.marker) } : { resource: null, selection: null, event: null, data: null }; - if (resource && selection) { + if (resource && selection && event) { /* __GDPR__ "problems.selectDiagnostic" : { "source": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, @@ -465,7 +465,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { private onSelected(): void { let selection = this.tree.getSelection(); if (selection && selection.length > 0) { - this.lastSelectedRelativeTop = this.tree.getRelativeTop(selection[0]); + this.lastSelectedRelativeTop = this.tree.getRelativeTop(selection[0]) || 0; } } @@ -612,7 +612,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { } private onContextMenu(e: ITreeContextMenuEvent): void { - if (!e.element) { + const element = e.element; + if (!element) { return; } @@ -620,8 +621,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { e.browserEvent.stopPropagation(); this.contextMenuService.showContextMenu({ - getAnchor: () => e.anchor, - getActions: () => this.getMenuActions(e.element), + getAnchor: () => e.anchor!, + getActions: () => this.getMenuActions(element), getActionItem: (action) => { const keybinding = this.keybindingService.lookupKeybinding(action.id); if (keybinding) { @@ -665,7 +666,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { return result; } - public getFocusElement(): TreeElement { + public getFocusElement() { return this.tree.getFocus()[0]; } diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index c7e69cc7584..b61a76f1283 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -67,7 +67,7 @@ export class MarkersTreeAccessibilityProvider implements IAccessibilityProvider< constructor(@ILabelService private readonly labelService: ILabelService) { } - public getAriaLabel(element: TreeElement): string { + public getAriaLabel(element: TreeElement): string | null { if (element instanceof ResourceMarkers) { const path = this.labelService.getUriLabel(element.resource, { relative: true }) || element.resource.fsPath; return Messages.MARKERS_TREE_ARIA_LABEL_RESOURCE(element.markers.length, element.name, paths.dirname(path)); @@ -262,7 +262,7 @@ class MarkerWidget extends Disposable { this._register(toDisposable(() => this.disposables = dispose(this.disposables))); } - render(element: Marker, filterData: MarkerFilterData): void { + render(element: Marker, filterData: MarkerFilterData | undefined): void { this.actionBar.clear(); this.multilineActionbar.clear(); if (this.disposables.length) { @@ -310,7 +310,7 @@ class MarkerWidget extends Disposable { this.multilineActionbar.push([action], { icon: true, label: false }); } - private renderMessageAndDetails(element: Marker, filterData: MarkerFilterData) { + private renderMessageAndDetails(element: Marker, filterData: MarkerFilterData | undefined) { const { marker, lines } = element; const viewState = this.markersViewModel.getViewModel(element); const multiline = !viewState || viewState.multiline; @@ -330,7 +330,7 @@ class MarkerWidget extends Disposable { this.renderDetails(marker, filterData, multiline ? lastLineElement : this.messageAndDetailsContainer); } - private renderDetails(marker: IMarker, filterData: MarkerFilterData, parent: HTMLElement): void { + private renderDetails(marker: IMarker, filterData: MarkerFilterData | undefined, parent: HTMLElement): void { dom.addClass(parent, 'details-container'); const sourceMatches = filterData && filterData.sourceMatches || []; const codeMatches = filterData && filterData.codeMatches || []; @@ -557,7 +557,7 @@ export class MarkerViewModel extends Disposable { return this.codeActionsPromise; } return this.getModel(waitForModel) - .then(model => { + .then(model => { if (model) { if (!this.codeActionsPromise) { this.codeActionsPromise = createCancelablePromise(cancellationToken => { @@ -629,7 +629,7 @@ export class MarkersViewModel extends Disposable { private bulkUpdate: boolean = false; - private hoveredMarker: Marker; + private hoveredMarker: Marker | null; private hoverDelayer: Delayer = new Delayer(300); constructor( From 13e394ff45191c972a4849ab17f3ce910914e71b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 11:25:32 -0800 Subject: [PATCH 111/172] Strict null fixes for tests --- src/vs/workbench/api/node/extHost.protocol.ts | 6 +++--- .../common/editor/untitledEditorInput.ts | 5 +++-- .../common/editor/untitledEditorModel.ts | 5 +++-- .../test/common/editor/untitledEditor.test.ts | 18 +++++++++--------- .../api/mainThreadEditors.test.ts | 8 ++++---- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 2e74617076a..07a015c08d7 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -860,9 +860,9 @@ export interface WorkspaceSymbolsDto extends IdObject { } export interface ResourceFileEditDto { - oldUri: UriComponents; - newUri: UriComponents; - options: IFileOperationOptions; + oldUri?: UriComponents; + newUri?: UriComponents; + options?: IFileOperationOptions; } export interface ResourceTextEditDto { diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 9d3ebed0a01..637ea614ee6 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -17,6 +17,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; import { ILabelService } from 'vs/platform/label/common/label'; +import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; /** * An editor input to be used for untitled text buffers. @@ -27,7 +28,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport private _hasAssociatedFilePath: boolean; private cachedModel: UntitledEditorModel; - private modelResolve?: Promise; + private modelResolve?: Promise; private readonly _onDidModelChangeContent: Emitter = this._register(new Emitter()); get onDidModelChangeContent(): Event { return this._onDidModelChangeContent.event; } @@ -199,7 +200,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport } } - resolve(): Promise { + resolve(): Promise { // Join a model resolve if we have had one before if (this.modelResolve) { diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index a19c5e64cf2..15c9bd51637 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -16,6 +16,7 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { ITextBufferFactory } from 'vs/editor/common/model'; import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; +import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; export class UntitledEditorModel extends BaseTextEditorModel implements IEncodingSupport { @@ -136,7 +137,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin this.contentChangeEventScheduler.schedule(); } - load(): Promise { + load(): Promise { // Check for backups first return this.backupFileService.loadBackupResource(this.resource).then((backupResource) => { @@ -180,7 +181,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin // Listen to mode changes this._register(textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config - return this; + return this as UntitledEditorModel & IResolvedTextEditorModel; }); } diff --git a/src/vs/workbench/test/common/editor/untitledEditor.test.ts b/src/vs/workbench/test/common/editor/untitledEditor.test.ts index 5ce1d30ace9..62403c94f5c 100644 --- a/src/vs/workbench/test/common/editor/untitledEditor.test.ts +++ b/src/vs/workbench/test/common/editor/untitledEditor.test.ts @@ -68,7 +68,7 @@ suite('Workbench untitled editors', () => { assert.equal(service.getAll().length, 1); // dirty - input2.resolve().then((model: UntitledEditorModel) => { + input2.resolve().then(model => { assert.ok(!service.isDirty(input2.getResource())); const listener = service.onDidChangeDirty(resource => { @@ -112,7 +112,7 @@ suite('Workbench untitled editors', () => { const input = service.createOrGet(); // dirty - return input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then(model => { model.textEditorModel.setValue('foo bar'); assert.ok(model.isDirty()); @@ -126,14 +126,14 @@ suite('Workbench untitled editors', () => { test('Untitled via loadOrCreate', function () { const service = accessor.untitledEditorService; service.loadOrCreate().then(model1 => { - model1.textEditorModel.setValue('foo bar'); + model1.textEditorModel!.setValue('foo bar'); assert.ok(model1.isDirty()); - model1.textEditorModel.setValue(''); + model1.textEditorModel!.setValue(''); assert.ok(!model1.isDirty()); return service.loadOrCreate({ initialValue: 'Hello World' }).then(model2 => { - assert.equal(snapshotToString(model2.createSnapshot()), 'Hello World'); + assert.equal(snapshotToString(model2.createSnapshot()!), 'Hello World'); const input = service.createOrGet(); @@ -169,7 +169,7 @@ suite('Workbench untitled editors', () => { const input = service.createOrGet(file); // dirty - return input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then(model => { model.textEditorModel.setValue('foo bar'); assert.ok(model.isDirty()); @@ -223,7 +223,7 @@ suite('Workbench untitled editors', () => { }); // dirty - return input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then(model => { model.setEncoding('utf16'); assert.equal(counter, 1); @@ -245,7 +245,7 @@ suite('Workbench untitled editors', () => { assert.equal(r.toString(), input.getResource().toString()); }); - return input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then(model => { model.textEditorModel.setValue('foo'); assert.equal(counter, 0, 'Dirty model should not trigger event immediately'); @@ -288,7 +288,7 @@ suite('Workbench untitled editors', () => { assert.equal(r.toString(), input.getResource().toString()); }); - return input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then(model => { assert.equal(counter, 0); input.dispose(); assert.equal(counter, 1); 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 fb0d2c8e3aa..74633e4d5ac 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts @@ -23,7 +23,7 @@ import { TestFileService, TestEditorService, TestEditorGroupsService, TestEnviro import { ResourceTextEdit } from 'vs/editor/common/modes'; import { BulkEditService } from 'vs/workbench/services/bulkEdit/browser/bulkEditService'; import { NullLogService } from 'vs/platform/log/common/log'; -import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IReference, ImmortalReference } from 'vs/base/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { LabelService } from 'vs/workbench/services/label/common/labelService'; @@ -73,9 +73,9 @@ suite('MainThreadEditors', () => { const workbenchEditorService = new TestEditorService(); const editorGroupService = new TestEditorGroupsService(); const textModelService = new class extends mock() { - createModelReference(resource: URI): Promise> { - const textEditorModel: ITextEditorModel = new class extends mock() { - textEditorModel = modelService.getModel(resource); + createModelReference(resource: URI): Promise> { + const textEditorModel = new class extends mock() { + textEditorModel = modelService.getModel(resource)!; }; textEditorModel.isReadonly = () => false; return Promise.resolve(new ImmortalReference(textEditorModel)); From 1f2dca36d9660f36506d636457a10973b6310c57 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 11:26:52 -0800 Subject: [PATCH 112/172] Strict null check textFileEditor --- src/tsconfig.strictNullChecks.json | 1 + src/vs/editor/common/services/resourceConfiguration.ts | 10 +++++----- .../contrib/files/browser/editors/textFileEditor.ts | 7 +++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 45b6c97b069..b97d15467c0 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -255,6 +255,7 @@ "./vs/workbench/contrib/feedback/electron-browser/feedbackStatusbarItem.ts", "./vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts", "./vs/workbench/contrib/files/browser/editors/fileEditorTracker.ts", + "./vs/workbench/contrib/files/browser/editors/textFileEditor.ts", "./vs/workbench/contrib/files/browser/files.ts", "./vs/workbench/contrib/files/browser/views/emptyView.ts", "./vs/workbench/contrib/files/browser/views/explorerDecorationsProvider.ts", diff --git a/src/vs/editor/common/services/resourceConfiguration.ts b/src/vs/editor/common/services/resourceConfiguration.ts index e0926ee9fda..02e63369296 100644 --- a/src/vs/editor/common/services/resourceConfiguration.ts +++ b/src/vs/editor/common/services/resourceConfiguration.ts @@ -24,13 +24,13 @@ export interface ITextResourceConfigurationService { * Fetches the value of the section for the given resource by applying language overrides. * Value can be of native type or an object keyed off the section name. * - * @param resource - Resource for which the configuration has to be fetched. Can be `null` or `undefined`. - * @param postion - Position in the resource for which configuration has to be fetched. Can be `null` or `undefined`. - * @param section - Section of the configuraion. Can be `null` or `undefined`. + * @param resource - Resource for which the configuration has to be fetched. + * @param postion - Position in the resource for which configuration has to be fetched. + * @param section - Section of the configuraion. * */ - getValue(resource: URI, section?: string): T; - getValue(resource: URI, position?: IPosition, section?: string): T; + getValue(resource: URI | undefined, section?: string): T; + getValue(resource: URI | undefined, position?: IPosition, section?: string): T; } diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index c5c6bcb72ca..c8241f591cb 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -82,7 +82,7 @@ export class TextFileEditor extends BaseTextEditor { } private updateRestoreViewStateConfiguration(): void { - this.restoreViewState = this.configurationService.getValue(null, 'workbench.editor.restoreViewState'); + this.restoreViewState = this.configurationService.getValue(undefined, 'workbench.editor.restoreViewState'); } getTitle(): string { @@ -198,7 +198,7 @@ export class TextFileEditor extends BaseTextEditor { } if ((error).fileOperationResult === FileOperationResult.FILE_EXCEED_MEMORY_LIMIT) { - const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.configurationService.getValue(null, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB); + const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.configurationService.getValue(undefined, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB); return Promise.reject(createErrorWithActions(toErrorMessage(error), { actions: [ @@ -228,6 +228,9 @@ export class TextFileEditor extends BaseTextEditor { } private openAsFolder(input: FileEditorInput): void { + if (!this.group) { + return; + } // Since we cannot open a folder, we have to restore the previous input if any and close the editor this.group.closeEditor(this.input).then(() => { From a6c498b74a33b3e219ff957cee1b7d37170c2102 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 11:38:28 -0800 Subject: [PATCH 113/172] Strict null check fileService --- src/tsconfig.strictNullChecks.json | 1 + .../workbench/services/files/node/encoding.ts | 2 +- .../services/files/node/fileService.ts | 36 ++++++++++--------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index b97d15467c0..c4464341e9b 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -409,6 +409,7 @@ "./vs/workbench/services/extensions/node/rpcProtocol.ts", "./vs/workbench/services/extensions/test/node/rpcProtocol.test.ts", "./vs/workbench/services/files/node/encoding.ts", + "./vs/workbench/services/files/node/fileService.ts", "./vs/workbench/services/files/node/streams.ts", "./vs/workbench/services/files/test/electron-browser/utils.ts", "./vs/workbench/services/files/test/electron-browser/watcher.test.ts", diff --git a/src/vs/workbench/services/files/node/encoding.ts b/src/vs/workbench/services/files/node/encoding.ts index b600d76c684..62067cb504f 100644 --- a/src/vs/workbench/services/files/node/encoding.ts +++ b/src/vs/workbench/services/files/node/encoding.ts @@ -49,7 +49,7 @@ export class ResourceEncodings extends Disposable implements IResourceEncodings })); } - getReadEncoding(resource: uri, options: IResolveContentOptions, detected: encoding.IDetectedEncodingResult): string { + getReadEncoding(resource: uri, options: IResolveContentOptions | undefined, detected: encoding.IDetectedEncodingResult): string { let preferredEncoding: string | undefined; // Encoding passed in as option diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index f9b20baae2e..3302a7b90a0 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -70,7 +70,7 @@ export class FileService extends Disposable implements IFileService { protected readonly _onDidChangeFileSystemProviderRegistrations = this._register(new Emitter()); get onDidChangeFileSystemProviderRegistrations(): Event { return this._onDidChangeFileSystemProviderRegistrations.event; } - private activeWorkspaceFileChangeWatcher: IDisposable; + private activeWorkspaceFileChangeWatcher: IDisposable | null; private activeFileChangesWatchers: ResourceMap<{ unwatch: Function, count: number }>; private fileChangesWatchDelayer: ThrottledDelayer; private undeliveredRawFileChangesEvents: IRawFileChange[]; @@ -262,7 +262,7 @@ export class FileService extends Disposable implements IFileService { )); } - const result: IStreamContent = { + const result: Partial = { resource: undefined, name: undefined, mtime: undefined, @@ -311,7 +311,7 @@ export class FileService extends Disposable implements IFileService { // Return early if file is too large to load if (typeof stat.size === 'number') { - if (stat.size > Math.max(parseInt(this.environmentService.args['max-memory']) * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { + if (stat.size > Math.max(typeof this.environmentService.args['max-memory'] === 'string' ? parseInt(this.environmentService.args['max-memory']) * 1024 * 1024 || 0 : 0, MAX_HEAP_SIZE)) { return onStatError(new FileOperationError( nls.localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart VS Code and allow it to use more memory"), FileOperationResult.FILE_EXCEED_MEMORY_LIMIT @@ -391,17 +391,17 @@ export class FileService extends Disposable implements IFileService { }); } - private fillInContents(content: IStreamContent, resource: uri, options: IResolveContentOptions, token: CancellationToken): Promise { + private fillInContents(content: Partial, resource: uri, options: IResolveContentOptions | undefined, token: CancellationToken): Promise { return this.resolveFileData(resource, options, token).then(data => { content.encoding = data.encoding; content.value = data.stream; }); } - private resolveFileData(resource: uri, options: IResolveContentOptions, token: CancellationToken): Promise { + private resolveFileData(resource: uri, options: IResolveContentOptions | undefined, token: CancellationToken): Promise { const chunkBuffer = Buffer.allocUnsafe(64 * 1024); - const result: IContentData = { + const result: Partial = { encoding: undefined, stream: undefined }; @@ -473,7 +473,7 @@ export class FileService extends Disposable implements IFileService { } }; - let currentPosition: number = (options && options.position) || null; + let currentPosition: number | null = (options && options.position) || null; const readChunk = () => { fs.read(fd, chunkBuffer, 0, chunkBuffer.length, currentPosition, (err, bytesRead) => { @@ -485,7 +485,7 @@ export class FileService extends Disposable implements IFileService { currentPosition += bytesRead; } - if (totalBytesRead > Math.max(parseInt(this.environmentService.args['max-memory']) * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { + if (totalBytesRead > Math.max(typeof this.environmentService.args['max-memory'] === 'number' ? parseInt(this.environmentService.args['max-memory']) * 1024 * 1024 || 0 : 0, MAX_HEAP_SIZE)) { finish(new FileOperationError( nls.localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart VS Code and allow it to use more memory"), FileOperationResult.FILE_EXCEED_MEMORY_LIMIT @@ -525,7 +525,7 @@ export class FileService extends Disposable implements IFileService { } else { result.encoding = this._encoding.getReadEncoding(resource, options, detected); result.stream = decoder = encoding.decodeStream(result.encoding); - resolve(result); + resolve(result as IContentData); handleChunk(bytesRead); } }).then(undefined, err => { @@ -1168,16 +1168,18 @@ export class StatResolver { let absoluteTargetPaths: string[] | null = null; if (options && options.resolveTo) { absoluteTargetPaths = []; - options.resolveTo.forEach(resource => { + for (const resource of options.resolveTo) { absoluteTargetPaths.push(resource.fsPath); - }); + } } return new Promise(resolve => { // Load children - this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, options && options.resolveSingleChildDescendants, children => { - children = arrays.coalesce(children); // we don't want those null children (could be permission denied when reading a child) + this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, !!(options && options.resolveSingleChildDescendants), children => { + if (children) { + children = arrays.coalesce(children); // we don't want those null children (could be permission denied when reading a child) + } fileStat.children = children || []; resolve(fileStat); @@ -1186,7 +1188,7 @@ export class StatResolver { } } - private resolveChildren(absolutePath: string, absoluteTargetPaths: string[], resolveSingleChildDescendants: boolean, callback: (children: IFileStat[]) => void): void { + private resolveChildren(absolutePath: string, absoluteTargetPaths: string[] | null, resolveSingleChildDescendants: boolean, callback: (children: IFileStat[] | null) => void): void { extfs.readdir(absolutePath, (error: Error, files: string[]) => { if (error) { if (this.errorLogger) { @@ -1197,7 +1199,7 @@ export class StatResolver { } // for each file in the folder - flow.parallel(files, (file: string, clb: (error: Error, children: IFileStat) => void) => { + flow.parallel(files, (file: string, clb: (error: Error | null, children: IFileStat | null) => void) => { const fileResource = uri.file(paths.resolve(absolutePath, file)); let fileStat: fs.Stats; let isSymbolicLink = false; @@ -1257,7 +1259,9 @@ export class StatResolver { // Continue resolving children based on condition if (resolveFolderChildren) { $this.resolveChildren(fileResource.fsPath, absoluteTargetPaths, resolveSingleChildDescendants, children => { - children = arrays.coalesce(children); // we don't want those null children + if (children) { + children = arrays.coalesce(children); // we don't want those null children + } childStat.children = children || []; clb(null, childStat); From f521072eccde9f258a20740a7ce5d98407de7530 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 12:01:14 -0800 Subject: [PATCH 114/172] Strict null check configurationEditingService --- src/tsconfig.strictNullChecks.json | 1 + .../node/configurationEditingService.ts | 52 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index c4464341e9b..5e4c68bfe68 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -381,6 +381,7 @@ "./vs/workbench/services/configuration/common/configurationModels.ts", "./vs/workbench/services/configuration/common/jsonEditing.ts", "./vs/workbench/services/configuration/node/configuration.ts", + "./vs/workbench/services/configuration/node/configurationEditingService.ts", "./vs/workbench/services/configuration/node/jsonEditingService.ts", "./vs/workbench/services/configuration/test/common/configurationModels.test.ts", "./vs/workbench/services/configurationResolver/common/configurationResolver.ts", diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 6943c5b3819..d559ff78819 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -22,7 +22,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; -import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; +import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextModel } from 'vs/editor/common/model'; @@ -106,7 +106,7 @@ export interface IConfigurationEditingOptions { interface IConfigurationEditOperation extends IConfigurationValue { target: ConfigurationTarget; jsonPath: json.JSONPath; - resource: URI; + resource?: URI; workspaceStandAloneConfigurationKey?: string; } @@ -158,7 +158,7 @@ export class ConfigurationEditingService { private async writeToBuffer(model: ITextModel, operation: IConfigurationEditOperation, save: boolean): Promise { const edit = this.getEdits(model, operation)[0]; if (edit && this.applyEditsToBuffer(edit, model) && save) { - return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }); + return this.textFileService.save(operation.resource!, { skipSaveParticipants: true /* programmatic change */ }); } } @@ -175,7 +175,7 @@ export class ConfigurationEditingService { return false; } - private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void { + private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void { switch (error.code) { case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION: this.onInvalidConfigurationError(error, operation); @@ -196,7 +196,7 @@ export class ConfigurationEditingService { this.notificationService.prompt(Severity.Error, error.message, [{ label: openStandAloneConfigurationActionLabel, - run: () => this.openFile(operation.resource) + run: () => this.openFile(operation.resource!) }] ); } else { @@ -209,7 +209,7 @@ export class ConfigurationEditingService { } } - private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void { + private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void { const openStandAloneConfigurationActionLabel = operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY ? nls.localize('openTasksConfiguration', "Open Tasks Configuration") : operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration") : null; @@ -218,13 +218,13 @@ export class ConfigurationEditingService { [{ label: nls.localize('saveAndRetry', "Save and Retry"), run: () => { - const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey; + const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey!; this.writeConfiguration(operation.target, { key, value: operation.value }, { force: true, scopes }); } }, { label: openStandAloneConfigurationActionLabel, - run: () => this.openFile(operation.resource) + run: () => this.openFile(operation.resource!) }] ); } else { @@ -296,7 +296,13 @@ export class ConfigurationEditingService { case ConfigurationTarget.WORKSPACE: return nls.localize('errorInvalidConfigurationWorkspace', "Unable to write into workspace settings. Please open the workspace settings to correct errors/warnings in the file and try again."); case ConfigurationTarget.WORKSPACE_FOLDER: - const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name; + let workspaceFolderName: string = '<>'; + if (operation.resource) { + const folder = this.contextService.getWorkspaceFolder(operation.resource); + if (folder) { + workspaceFolderName = folder.name; + } + } return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName); } return ''; @@ -314,7 +320,13 @@ export class ConfigurationEditingService { case ConfigurationTarget.WORKSPACE: return nls.localize('errorConfigurationFileDirtyWorkspace', "Unable to write into workspace settings because the file is dirty. Please save the workspace settings file first and then try again."); case ConfigurationTarget.WORKSPACE_FOLDER: - const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name; + let workspaceFolderName: string = '<>'; + if (operation.resource) { + const folder = this.contextService.getWorkspaceFolder(operation.resource); + if (folder) { + workspaceFolderName = folder.name; + } + } return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName); } return ''; @@ -352,7 +364,7 @@ export class ConfigurationEditingService { return setProperty(model.getValue(), jsonPath, value, { tabSize, insertSpaces, eol }); } - private async resolveModelReference(resource: URI): Promise> { + private async resolveModelReference(resource: URI): Promise> { const exists = await this.fileService.existsFile(resource); if (!exists) { await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 }); @@ -371,7 +383,7 @@ export class ConfigurationEditingService { return parseErrors.length > 0; } - private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise> { + private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise> { // Any key must be a known setting from the registry (unless this is a standalone config) if (!operation.workspaceStandAloneConfigurationKey) { @@ -420,6 +432,10 @@ export class ConfigurationEditingService { } } + if (!operation.resource) { + return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_TARGET, target, operation); + } + return this.resolveModelReference(operation.resource) .then(reference => { const model = reference.object.textEditorModel; @@ -447,14 +463,14 @@ export class ConfigurationEditingService { // Check for prefix if (config.key === key) { const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key] : []; - return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target }; + return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target }; } // Check for prefix. const keyPrefix = `${key}.`; if (config.key.indexOf(keyPrefix) === 0) { const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; - return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target }; + return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target }; } } } @@ -469,15 +485,15 @@ export class ConfigurationEditingService { if (this.isWorkspaceConfigurationResource(resource)) { jsonPath = ['settings', ...jsonPath]; } - return { key, jsonPath, value: config.value, resource, target }; + return { key, jsonPath, value: config.value, resource: resource || undefined, target }; } - private isWorkspaceConfigurationResource(resource: URI): boolean { + private isWorkspaceConfigurationResource(resource: URI | null | undefined): boolean { const workspace = this.contextService.getWorkspace(); return !!(workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath); } - private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI): URI { + private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI | null | undefined): URI | null { if (target === ConfigurationTarget.USER) { return URI.file(this.environmentService.appSettingsPath); } @@ -489,7 +505,7 @@ export class ConfigurationEditingService { if (target === ConfigurationTarget.WORKSPACE) { if (workbenchState === WorkbenchState.WORKSPACE) { - return workspace.configuration; + return workspace.configuration || null; } if (workbenchState === WorkbenchState.FOLDER) { return workspace.folders[0].toResource(relativePath); From 37732e9cedbb5de49e5b1af3ae4656a420f8892e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 13:01:27 -0800 Subject: [PATCH 115/172] Strict null check titlebarPart --- src/tsconfig.strictNullChecks.json | 1 + src/vs/base/common/labels.ts | 2 +- .../workbench/browser/parts/titlebar/titlebarPart.ts | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 5e4c68bfe68..472a84395ad 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -147,6 +147,7 @@ "./vs/workbench/browser/parts/statusbar/statusbar.ts", "./vs/workbench/browser/parts/statusbar/statusbarPart.ts", "./vs/workbench/browser/parts/titlebar/menubarControl.ts", + "./vs/workbench/browser/parts/titlebar/titlebarPart.ts", "./vs/workbench/browser/parts/views/customView.ts", "./vs/workbench/browser/parts/views/panelViewlet.ts", "./vs/workbench/browser/parts/views/views.ts", diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index dc55a8db24a..aea4b726f2f 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -283,7 +283,7 @@ interface ISegment { * @param value string to which templating is applied * @param values the values of the templates to use */ -export function template(template: string, values: { [key: string]: string | ISeparator } = Object.create(null)): string { +export function template(template: string, values: { [key: string]: string | ISeparator | null } = Object.create(null)): string { const segments: ISegment[] = []; let inVariable = false; diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 768cbe3ef10..9bb6b629cf9 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -180,7 +180,7 @@ export class TitlebarPart extends Part implements ITitleService, ISerializableVi } private updateRepresentedFilename(): void { - const file = toResource(this.editorService.activeEditor, { supportSideBySide: true, filter: 'file' }); + const file = toResource(this.editorService.activeEditor || null, { supportSideBySide: true, filter: 'file' }); const path = file ? file.fsPath : ''; // Apply to window @@ -283,7 +283,7 @@ export class TitlebarPart extends Part implements ITitleService, ISerializableVi // 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: true })); + const folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor || null, { supportSideBySide: true })!); // Variables const activeEditorShort = editor ? editor.getTitle(Verbosity.SHORT) : ''; @@ -473,7 +473,7 @@ export class TitlebarPart extends Part implements ITitleService, ISerializableVi const titleBackground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND); this.element.style.backgroundColor = titleBackground; - if (Color.fromHex(titleBackground).isLighter()) { + if (titleBackground && Color.fromHex(titleBackground).isLighter()) { addClass(this.element, 'light'); } else { removeClass(this.element, 'light'); @@ -582,7 +582,7 @@ export class TitlebarPart extends Part implements ITitleService, ISerializableVi runAtThisOrScheduleAtNextAnimationFrame(() => this.adjustTitleMarginToCenter()); if (this.menubarPart) { - const menubarDimension = new Dimension(undefined, dimension.height); + const menubarDimension = new Dimension(0, dimension.height); this.menubarPart.layout(menubarDimension); } } @@ -597,7 +597,7 @@ export class TitlebarPart extends Part implements ITitleService, ISerializableVi return super.layout(dim1); } - const dimensions = new Dimension(dim1, dim2); + const dimensions = new Dimension(dim1, dim2!); this.updateLayout(dimensions); super.layout(dimensions); From d862e3217a5b3b96935b22c6d2c1d6f3f242cddd Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 12:16:08 -0800 Subject: [PATCH 116/172] Fix #66796 - previously there was weird listener behavior described in that issue but it has disappeared --- .../preferences/electron-browser/settingsEditor2.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts index 522b03a65a2..e33e245fe49 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts @@ -583,11 +583,8 @@ export class SettingsEditor2 extends BaseEditor { if (this.searchResultModel) { if (this.viewState.filterToCategory !== element) { this.viewState.filterToCategory = element; - // see https://github.com/Microsoft/vscode/issues/66796 - setTimeout(() => { - this.renderTree(); - this.settingsTree.scrollTop = 0; - }, 0); + this.renderTree(); + this.settingsTree.scrollTop = 0; } } else if (element && (!e.browserEvent || !(e.browserEvent).fromScroll)) { this.settingsTree.reveal(element, 0); From b7673fb6f4f280c4ea6b9e7bdd22fb5dabebdc45 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 12:18:56 -0800 Subject: [PATCH 117/172] :lipstick: --- .../preferences/electron-browser/settingsEditor2.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts index e33e245fe49..e30905c2ebe 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts @@ -56,6 +56,10 @@ function createGroupIterator(group: SettingsTreeGroupElement): Iteratore.browserEvent).fromScroll)) { + } else if (element && (!e.browserEvent || !(e.browserEvent).fromScroll)) { this.settingsTree.reveal(element, 0); } })); @@ -709,7 +713,7 @@ export class SettingsEditor2 extends BaseEditor { this.tocTree.setSelection([element]); const fakeKeyboardEvent = new KeyboardEvent('keydown'); - (fakeKeyboardEvent).fromScroll = true; + (fakeKeyboardEvent).fromScroll = true; this.tocTree.setFocus([element], fakeKeyboardEvent); } } From 8764eaf579c40396438d260573f9f002c774204e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 12:43:17 -0800 Subject: [PATCH 118/172] Fix #64749 - firstVisibleIndex in tree should consider element midpoint --- src/vs/base/browser/ui/list/listView.ts | 9 +++++ .../electron-browser/settingsEditor2.ts | 33 ++----------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index ac85245b2fe..a4f93a958c7 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -445,6 +445,15 @@ export class ListView implements ISpliceable, IDisposable { get firstVisibleIndex(): number { const range = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + const firstElTop = this.rangeMap.positionAt(range.start); + const nextElTop = this.rangeMap.positionAt(range.start + 1); + if (nextElTop !== -1) { + const firstElMidpoint = (nextElTop - firstElTop) / 2 + firstElTop; + if (firstElMidpoint < this.scrollTop) { + return range.start + 1; + } + } + return range.start; } diff --git a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts index e30905c2ebe..efdfdce5654 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts @@ -273,9 +273,6 @@ export class SettingsEditor2 extends BaseEditor { } layout(dimension: DOM.Dimension): void { - // const firstEl = this.settingsTree.getFirstVisibleElement(); - // const firstElTop = this.settingsTree.getRelativeTop(firstEl); - this.layoutTrees(dimension); const innerWidth = dimension.width - 24 * 2; // 24px padding on left and right @@ -497,7 +494,7 @@ export class SettingsEditor2 extends BaseEditor { e => { if (DOM.findParentWithClass(e.relatedTarget, 'settings-editor-tree')) { if (this.settingsTree.scrollTop > 0) { - const firstElement = this.getFirstVisibleElement(); + const firstElement = this.settingsTree.firstVisibleElement; this.settingsTree.reveal(firstElement, 0.1); return true; } @@ -519,7 +516,7 @@ export class SettingsEditor2 extends BaseEditor { e => { if (DOM.findParentWithClass(e.relatedTarget, 'settings-editor-tree')) { if (this.settingsTree.scrollTop < this.settingsTree.scrollHeight) { - const lastElement = this.getLastVisibleElement(); + const lastElement = this.settingsTree.lastVisibleElement; this.settingsTree.reveal(lastElement, 0.9); return true; } @@ -531,30 +528,6 @@ export class SettingsEditor2 extends BaseEditor { ); } - private getFirstVisibleElement(nth = 0): SettingsTreeElement | null { - // Hack, see https://github.com/Microsoft/vscode/issues/64749 - const settingItems = this.settingsTree.getHTMLElement().querySelectorAll(AbstractSettingRenderer.CONTENTS_SELECTOR); - const firstEl = settingItems[nth] || settingItems[0]; - if (!firstEl) { - return null; - } - - const firstSettingId = this.settingRenderers.getIdForDOMElementInSetting(firstEl); - return this.settingsTreeModel.getElementById(firstSettingId); - } - - private getLastVisibleElement(): SettingsTreeElement | null { - // Hack, see https://github.com/Microsoft/vscode/issues/64749 - const settingItems = this.settingsTree.getHTMLElement().querySelectorAll(AbstractSettingRenderer.CONTENTS_SELECTOR); - const firstEl = settingItems[settingItems.length - 1]; - if (!firstEl) { - return null; - } - - const firstSettingId = this.settingRenderers.getIdForDOMElementInSetting(firstEl); - return this.settingsTreeModel.getElementById(firstSettingId); - } - private createFocusSink(container: HTMLElement, callback: (e: any) => boolean, label: string): HTMLElement { const listFocusSink = DOM.append(container, $('.settings-tree-focus-sink')); listFocusSink.setAttribute('aria-label', label); @@ -688,7 +661,7 @@ export class SettingsEditor2 extends BaseEditor { return; } - const elementToSync = this.getFirstVisibleElement(1); + const elementToSync = this.settingsTree.firstVisibleElement; const element = elementToSync instanceof SettingsTreeSettingElement ? elementToSync.parent : elementToSync instanceof SettingsTreeGroupElement ? elementToSync : null; From f3b73b1abc694c9d61b5c58832e02c1f2a0792a8 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 11:07:44 -0800 Subject: [PATCH 119/172] Fix #69862 - don't split comma-separated globs when expandPatterns is disabled (for findFiles) --- src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts | 1 + src/vs/workbench/contrib/search/common/queryBuilder.ts | 4 ++-- .../contrib/search/test/common/queryBuilder.test.ts | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 63d67c6aa05..fa5e5cc13b8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -181,6 +181,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { const query = queryBuilder.file(folders, { _reason: 'checkExists', includePattern: includes.join(', '), + expandPatterns: true, exists: true }); diff --git a/src/vs/workbench/contrib/search/common/queryBuilder.ts b/src/vs/workbench/contrib/search/common/queryBuilder.ts index ccf08d86b81..2cc16e6d342 100644 --- a/src/vs/workbench/contrib/search/common/queryBuilder.ts +++ b/src/vs/workbench/contrib/search/common/queryBuilder.ts @@ -152,14 +152,14 @@ export class QueryBuilder { if (options.includePattern) { includeSearchPathsInfo = options.expandPatterns ? this.parseSearchPaths(options.includePattern) : - { pattern: patternListToIExpression(...splitGlobPattern(options.includePattern)) }; + { pattern: patternListToIExpression(options.includePattern) }; } let excludeSearchPathsInfo: ISearchPathsInfo = {}; if (options.excludePattern) { excludeSearchPathsInfo = options.expandPatterns ? this.parseSearchPaths(options.excludePattern) : - { pattern: patternListToIExpression(...splitGlobPattern(options.excludePattern)) }; + { pattern: patternListToIExpression(options.excludePattern) }; } // Build folderQueries from searchPaths, if given, otherwise folderResources diff --git a/src/vs/workbench/contrib/search/test/common/queryBuilder.test.ts b/src/vs/workbench/contrib/search/test/common/queryBuilder.test.ts index 5fc42bc4901..aaa35bae3db 100644 --- a/src/vs/workbench/contrib/search/test/common/queryBuilder.test.ts +++ b/src/vs/workbench/contrib/search/test/common/queryBuilder.test.ts @@ -85,7 +85,7 @@ suite('QueryBuilder', () => { }); }); - test('splits glob pattern even with expandPatterns disabled', () => { + test('does not split glob pattern when expandPatterns disabled', () => { assertEqualQueries( queryBuilder.file([ROOT_1_URI], { includePattern: '**/foo, **/bar' }), { @@ -94,8 +94,7 @@ suite('QueryBuilder', () => { }], type: QueryType.File, includePattern: { - '**/foo': true, - '**/bar': true + '**/foo, **/bar': true } }); }); From 10fdea204aec021914d473d6ac019c6064ce4620 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 10:36:18 -0800 Subject: [PATCH 120/172] Fix #69840 --- .../src/singlefolder-tests/workspace.test.ts | 9 ++++++++- .../api/electron-browser/mainThreadWorkspace.ts | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index 1deca1ad443..2f46c461b3f 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -488,7 +488,14 @@ suite('workspace-namespace', () => { }); test('findFiles', () => { - return vscode.workspace.findFiles('*.png').then((res) => { + return vscode.workspace.findFiles('**/*.png').then((res) => { + assert.equal(res.length, 2); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + }); + }); + + test('findFiles, exclude', () => { + return vscode.workspace.findFiles('**/*.png', '**/sub/**').then((res) => { assert.equal(res.length, 1); assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); }); diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index fa5e5cc13b8..fe39eeef61a 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -134,6 +134,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { disregardSearchExcludeSettings: true, disregardIgnoreFiles: true, includePattern, + excludePattern: typeof excludePatternOrDisregardExcludes === 'string' ? excludePatternOrDisregardExcludes : undefined, _reason: 'startFileSearch' }); From 6770dd762d5ce0293ea9b58611a4f922979d4b5a Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Tue, 5 Mar 2019 16:02:39 -0800 Subject: [PATCH 121/172] fix/69830 --- src/vs/base/browser/ui/menu/menubar.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index 289bfd8f369..a4283053ab0 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -954,6 +954,16 @@ class ModifierKeyEmitter extends Emitter { this._keyStatus.lastKeyPressed = undefined; })); + this._subscriptions.push(domEvent(document.body, 'mouseup', true)(e => { + this._keyStatus.lastKeyPressed = undefined; + })); + + this._subscriptions.push(domEvent(document.body, 'mousemove', true)(e => { + if (e.buttons) { + this._keyStatus.lastKeyPressed = undefined; + } + })); + this._subscriptions.push(domEvent(window, 'blur')(e => { this._keyStatus.lastKeyPressed = undefined; this._keyStatus.lastKeyReleased = undefined; From e3964c95d232688eeb9585d96d4382be9c728537 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 14:14:06 -0800 Subject: [PATCH 122/172] Strict null check webview --- src/tsconfig.strictNullChecks.json | 9 +++++++-- .../webview/electron-browser/webviewEditorService.ts | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 472a84395ad..d35a1a5d671 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -29,7 +29,8 @@ "./vs/workbench/services/bulkEdit/**/*.ts", "./vs/workbench/services/progress/**/*.ts", "./vs/workbench/services/preferences/**/*.ts", - "./vs/workbench/services/timer/**/*.ts" + "./vs/workbench/services/timer/**/*.ts", + "./vs/workbench/contrib/webview/**/*.ts" ], "files": [ "./vs/monaco.d.ts", @@ -238,8 +239,10 @@ "./vs/workbench/contrib/extensions/common/extensionsFileTemplate.ts", "./vs/workbench/contrib/extensions/common/extensionsInput.ts", "./vs/workbench/contrib/extensions/common/extensionsUtils.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts", + "./vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsActivationProgress.ts", "./vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler.ts", @@ -370,8 +373,10 @@ "./vs/workbench/contrib/terminal/test/node/terminalEnvironment.test.ts", "./vs/workbench/contrib/themes/browser/themes.contribution.ts", "./vs/workbench/contrib/themes/test/electron-browser/themes.test.contribution.ts", + "./vs/workbench/contrib/update/electron-browser/releaseNotesEditor.ts", + "./vs/workbench/contrib/update/electron-browser/update.contribution.ts", + "./vs/workbench/contrib/update/electron-browser/update.ts", "./vs/workbench/contrib/url/common/url.contribution.ts", - "./vs/workbench/contrib/webview/electron-browser/webviewProtocols.ts", "./vs/workbench/electron-browser/window.ts", "./vs/workbench/services/activity/browser/activityService.ts", "./vs/workbench/services/activity/common/activity.ts", diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewEditorService.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewEditorService.ts index 234d1a1bcad..4fdb9469e84 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewEditorService.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewEditorService.ts @@ -12,6 +12,7 @@ import * as vscode from 'vscode'; import { WebviewEditorInput, RevivedWebviewEditorInput } from './webviewEditorInput'; import { GroupIdentifier } from 'vs/workbench/common/editor'; import { equals } from 'vs/base/common/arrays'; +import { values } from 'vs/base/common/map'; export const IWebviewEditorService = createDecorator('webviewEditorService'); @@ -169,7 +170,7 @@ export class WebviewEditorService implements IWebviewEditorService { canRevive( webview: WebviewEditorInput ): boolean { - for (const reviver of this._revivers) { + for (const reviver of values(this._revivers)) { if (reviver.canRevive(webview)) { return true; } @@ -180,7 +181,7 @@ export class WebviewEditorService implements IWebviewEditorService { private async tryRevive( webview: WebviewEditorInput ): Promise { - for (const reviver of this._revivers) { + for (const reviver of values(this._revivers)) { if (reviver.canRevive(webview)) { await reviver.reviveWebview(webview); return true; From 480b838ef2e1851aeb80c2cd965140e09c831b27 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 14:26:03 -0800 Subject: [PATCH 123/172] Strict null check apiCommands --- src/tsconfig.strictNullChecks.json | 1 + src/vs/editor/common/core/editOperation.ts | 4 ++-- src/vs/editor/common/model.ts | 2 +- src/vs/editor/contrib/format/formattingEdit.ts | 2 +- src/vs/monaco.d.ts | 2 +- .../mainThreadSaveParticipant.ts | 12 ++++++------ .../api/node/extHostDocumentsAndEditors.ts | 14 +++++++------- src/vs/workbench/api/node/extHostTextEditor.ts | 18 +++++++++--------- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index d35a1a5d671..1dc078954e6 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -74,6 +74,7 @@ "./vs/workbench/api/electron-browser/mainThreadUrls.ts", "./vs/workbench/api/electron-browser/mainThreadWindow.ts", "./vs/workbench/api/electron-browser/mainThreadWorkspace.ts", + "./vs/workbench/api/node/apiCommands.ts", "./vs/workbench/api/node/extHost.protocol.ts", "./vs/workbench/api/node/extHostClipboard.ts", "./vs/workbench/api/node/extHostConfiguration.ts", diff --git a/src/vs/editor/common/core/editOperation.ts b/src/vs/editor/common/core/editOperation.ts index fe3cf2e6084..9029c7a3cf4 100644 --- a/src/vs/editor/common/core/editOperation.ts +++ b/src/vs/editor/common/core/editOperation.ts @@ -24,14 +24,14 @@ export class EditOperation { }; } - public static replace(range: Range, text: string): IIdentifiedSingleEditOperation { + public static replace(range: Range, text: string | null): IIdentifiedSingleEditOperation { return { range: range, text: text }; } - public static replaceMove(range: Range, text: string): IIdentifiedSingleEditOperation { + public static replaceMove(range: Range, text: string | null): IIdentifiedSingleEditOperation { return { range: range, text: text, diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index a15dd004bef..48a268b0bd6 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -289,7 +289,7 @@ export interface ISingleEditOperation { /** * The text to replace with. This can be null to emulate a simple delete. */ - text: string; + text: string | null; /** * This indicates that this operation has "insert" semantics. * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. diff --git a/src/vs/editor/contrib/format/formattingEdit.ts b/src/vs/editor/contrib/format/formattingEdit.ts index 23bab3f1830..27dbbd06762 100644 --- a/src/vs/editor/contrib/format/formattingEdit.ts +++ b/src/vs/editor/contrib/format/formattingEdit.ts @@ -45,7 +45,7 @@ export class FormattingEdit { static execute(editor: ICodeEditor, _edits: TextEdit[]) { editor.pushUndoStop(); - let edits = FormattingEdit._handleEolEdits(editor, _edits); + const edits = FormattingEdit._handleEolEdits(editor, _edits); if (edits.length === 1 && FormattingEdit._isFullModelReplaceEdit(editor, edits[0])) { // We use replace semantics and hope that markers stay put... editor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text))); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 3f279a4527c..af4d3f7f0d6 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1387,7 +1387,7 @@ declare namespace monaco.editor { /** * The text to replace with. This can be null to emulate a simple delete. */ - text: string; + text: string | null; /** * This indicates that this operation has "insert" semantics. * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index f83e76de7a4..32c7b8403af 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -16,8 +16,8 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { IIdentifiedSingleEditOperation, ISingleEditOperation, ITextModel } from 'vs/editor/common/model'; -import { CodeAction } from 'vs/editor/common/modes'; +import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model'; +import { CodeAction, TextEdit } from 'vs/editor/common/modes'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction'; @@ -234,7 +234,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { const timeout = this._configurationService.getValue('editor.formatOnSaveTimeout', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() }); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { let source = new CancellationTokenSource(); let request = getDocumentFormattingEdits(this._telemetryService, this._editorWorkerService, model, model.getFormattingOptions(), FormatMode.Auto, source.token); @@ -257,11 +257,11 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { }); } - private _editsWithEditor(editor: ICodeEditor, edits: ISingleEditOperation[]): void { + private _editsWithEditor(editor: ICodeEditor, edits: TextEdit[]): void { FormattingEdit.execute(editor, edits); } - private _editWithModel(model: ITextModel, edits: ISingleEditOperation[]): void { + private _editWithModel(model: ITextModel, edits: TextEdit[]): void { const [{ range }] = edits; const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); @@ -276,7 +276,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { }); } - private static _asIdentEdit({ text, range }: ISingleEditOperation): IIdentifiedSingleEditOperation { + private static _asIdentEdit({ text, range }: TextEdit): IIdentifiedSingleEditOperation { return { text, range: Range.lift(range), diff --git a/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts b/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts index 57868da0161..c0e26886a58 100644 --- a/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts +++ b/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts @@ -17,7 +17,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha private _disposables: Disposable[] = []; - private _activeEditorId: string; + private _activeEditorId: string | null; private readonly _editors = new Map(); private readonly _documents = new Map(); @@ -25,12 +25,12 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha private readonly _onDidAddDocuments = new Emitter(); private readonly _onDidRemoveDocuments = new Emitter(); private readonly _onDidChangeVisibleTextEditors = new Emitter(); - private readonly _onDidChangeActiveTextEditor = new Emitter(); + private readonly _onDidChangeActiveTextEditor = new Emitter(); readonly onDidAddDocuments: Event = this._onDidAddDocuments.event; readonly onDidRemoveDocuments: Event = this._onDidRemoveDocuments.event; readonly onDidChangeVisibleTextEditors: Event = this._onDidChangeVisibleTextEditors.event; - readonly onDidChangeActiveTextEditor: Event = this._onDidChangeActiveTextEditor.event; + readonly onDidChangeActiveTextEditor: Event = this._onDidChangeActiveTextEditor.event; constructor( private readonly _mainContext: IMainContext, @@ -93,14 +93,14 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha assert.ok(this._documents.has(resource.toString()), `document '${resource}' does not exist`); assert.ok(!this._editors.has(data.id), `editor '${data.id}' already exists!`); - const documentData = this._documents.get(resource.toString()); + const documentData = this._documents.get(resource.toString())!; const editor = new ExtHostTextEditor( this._mainContext.getProxy(MainContext.MainThreadTextEditors), data.id, documentData, data.selections.map(typeConverters.Selection.to), data.options, - data.visibleRanges.map(typeConverters.Range.to), + data.visibleRanges.map(range => typeConverters.Range.to(range)), typeof data.editorPosition === 'number' ? typeConverters.ViewColumn.to(data.editorPosition) : undefined ); this._editors.set(data.id, editor); @@ -131,7 +131,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha } } - getDocument(uri: URI): ExtHostDocumentData { + getDocument(uri: URI): ExtHostDocumentData | undefined { return this._documents.get(uri.toString()); } @@ -141,7 +141,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha return result; } - getEditor(id: string): ExtHostTextEditor { + getEditor(id: string): ExtHostTextEditor | undefined { return this._editors.get(id); } diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index 3cb2231f1b8..ae9ea2f67cf 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -35,7 +35,7 @@ export class TextEditorDecorationType implements vscode.TextEditorDecorationType export interface ITextEditOperation { range: vscode.Range; - text: string; + text: string | null; forceMoveMarkers: boolean; } @@ -105,7 +105,7 @@ export class TextEditorEdit { this._pushEdit(range, null, true); } - private _pushEdit(range: Range, text: string, forceMoveMarkers: boolean): void { + private _pushEdit(range: Range, text: string | null, forceMoveMarkers: boolean): void { let validRange = this._document.validateRange(range); this._collectedEdits.push({ range: validRange, @@ -373,7 +373,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { private _selections: Selection[]; private _options: ExtHostTextEditorOptions; private _visibleRanges: Range[]; - private _viewColumn: vscode.ViewColumn; + private _viewColumn: vscode.ViewColumn | undefined; private _disposed: boolean = false; private _hasDecorationsForKey: { [key: string]: boolean; }; @@ -382,7 +382,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { constructor( proxy: MainThreadTextEditorsShape, id: string, document: ExtHostDocumentData, selections: Selection[], options: IResolvedTextEditorConfiguration, - visibleRanges: Range[], viewColumn: vscode.ViewColumn + visibleRanges: Range[], viewColumn: vscode.ViewColumn | undefined ) { this._proxy = proxy; this._id = id; @@ -451,7 +451,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { // ---- view column - get viewColumn(): vscode.ViewColumn { + get viewColumn(): vscode.ViewColumn | undefined { return this._viewColumn; } @@ -538,7 +538,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { ); } - private _trySetSelection(): Promise { + private _trySetSelection(): Promise { let selection = this._selections.map(TypeConverters.Selection.from); return this._runOnProxy(() => this._proxy.$trySetSelections(this._id, selection)); } @@ -598,7 +598,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { } // prepare data for serialization - let edits: ISingleEditOperation[] = editData.edits.map((edit) => { + const edits = editData.edits.map((edit): ISingleEditOperation => { return { range: TypeConverters.Range.from(edit.range), text: edit.text, @@ -620,7 +620,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { let ranges: IRange[]; if (!where || (Array.isArray(where) && where.length === 0)) { - ranges = this._selections.map(TypeConverters.Range.from); + ranges = this._selections.map(range => TypeConverters.Range.from(range)); } else if (where instanceof Position) { const { lineNumber, column } = TypeConverters.Position.from(where); @@ -645,7 +645,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { // ---- util - private _runOnProxy(callback: () => Promise): Promise { + private _runOnProxy(callback: () => Promise): Promise { if (this._disposed) { console.warn('TextEditor is closed/disposed'); return Promise.resolve(undefined); From 733a1cd8417309e1009e2eb28f5378cd63059c0a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 14:32:57 -0800 Subject: [PATCH 124/172] Strict null check extHostDocuments --- src/tsconfig.strictNullChecks.json | 9 ++++++++ src/vs/workbench/api/node/extHostDocuments.ts | 21 ++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 1dc078954e6..4028b21f89c 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -80,17 +80,26 @@ "./vs/workbench/api/node/extHostConfiguration.ts", "./vs/workbench/api/node/extHostDecorations.ts", "./vs/workbench/api/node/extHostDialogs.ts", + "./vs/workbench/api/node/extHostDocumentContentProviders.ts", "./vs/workbench/api/node/extHostDocumentData.ts", + "./vs/workbench/api/node/extHostDocuments.ts", + "./vs/workbench/api/node/extHostDocumentsAndEditors.ts", "./vs/workbench/api/node/extHostExtensionActivator.ts", + "./vs/workbench/api/node/extHostFileSystemEventService.ts", "./vs/workbench/api/node/extHostHeapService.ts", + "./vs/workbench/api/node/extHostLanguages.ts", "./vs/workbench/api/node/extHostLogService.ts", "./vs/workbench/api/node/extHostMessageService.ts", "./vs/workbench/api/node/extHostOutputService.ts", + "./vs/workbench/api/node/extHostProgress.ts", "./vs/workbench/api/node/extHostSearch.fileIndex.ts", "./vs/workbench/api/node/extHostSearch.ts", "./vs/workbench/api/node/extHostStorage.ts", + "./vs/workbench/api/node/extHostTextEditor.ts", + "./vs/workbench/api/node/extHostTypeConverters.ts", "./vs/workbench/api/node/extHostTypes.ts", "./vs/workbench/api/node/extHostUrls.ts", + "./vs/workbench/api/node/extHostWebview.ts", "./vs/workbench/api/node/extHostWindow.ts", "./vs/workbench/api/node/extHostWorkspace.ts", "./vs/workbench/api/shared/editor.ts", diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index a053696d1cf..40ae4c8a371 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -103,8 +103,10 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { public $acceptModelModeChanged(uriComponents: UriComponents, oldModeId: string, newModeId: string): void { const uri = URI.revive(uriComponents); - let data = this._documentsAndEditors.getDocument(uri); - + const data = this._documentsAndEditors.getDocument(uri); + if (!data) { + throw new Error('unknown document'); + } // Treat a mode change as a remove + add this._onDidRemoveDocument.fire(data.document); @@ -114,14 +116,20 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { public $acceptModelSaved(uriComponents: UriComponents): void { const uri = URI.revive(uriComponents); - let data = this._documentsAndEditors.getDocument(uri); + const data = this._documentsAndEditors.getDocument(uri); + if (!data) { + throw new Error('unknown document'); + } this.$acceptDirtyStateChanged(uriComponents, false); this._onDidSaveDocument.fire(data.document); } public $acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void { const uri = URI.revive(uriComponents); - let data = this._documentsAndEditors.getDocument(uri); + const data = this._documentsAndEditors.getDocument(uri); + if (!data) { + throw new Error('unknown document'); + } data._acceptIsDirty(isDirty); this._onDidChangeDocument.fire({ document: data.document, @@ -131,7 +139,10 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { public $acceptModelChanged(uriComponents: UriComponents, events: IModelChangedEvent, isDirty: boolean): void { const uri = URI.revive(uriComponents); - let data = this._documentsAndEditors.getDocument(uri); + const data = this._documentsAndEditors.getDocument(uri); + if (!data) { + throw new Error('unknown document'); + } data._acceptIsDirty(isDirty); data.onEvents(events); this._onDidChangeDocument.fire({ From bb64391ec4ea6d59f6f8664e81e58fe4da734673 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 14:41:15 -0800 Subject: [PATCH 125/172] Strict null work in exthost --- src/tsconfig.strictNullChecks.json | 4 ++++ src/vs/workbench/api/node/extHostCLIServer.ts | 2 +- src/vs/workbench/api/node/extHostCommands.ts | 2 +- .../api/node/extHostDocumentSaveParticipant.ts | 2 +- src/vs/workbench/api/node/extHostTextEditors.ts | 12 +++++++++--- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 4028b21f89c..c8f807a4283 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -76,12 +76,15 @@ "./vs/workbench/api/electron-browser/mainThreadWorkspace.ts", "./vs/workbench/api/node/apiCommands.ts", "./vs/workbench/api/node/extHost.protocol.ts", + "./vs/workbench/api/node/extHostCLIServer.ts", "./vs/workbench/api/node/extHostClipboard.ts", + "./vs/workbench/api/node/extHostCommands.ts", "./vs/workbench/api/node/extHostConfiguration.ts", "./vs/workbench/api/node/extHostDecorations.ts", "./vs/workbench/api/node/extHostDialogs.ts", "./vs/workbench/api/node/extHostDocumentContentProviders.ts", "./vs/workbench/api/node/extHostDocumentData.ts", + "./vs/workbench/api/node/extHostDocumentSaveParticipant.ts", "./vs/workbench/api/node/extHostDocuments.ts", "./vs/workbench/api/node/extHostDocumentsAndEditors.ts", "./vs/workbench/api/node/extHostExtensionActivator.ts", @@ -96,6 +99,7 @@ "./vs/workbench/api/node/extHostSearch.ts", "./vs/workbench/api/node/extHostStorage.ts", "./vs/workbench/api/node/extHostTextEditor.ts", + "./vs/workbench/api/node/extHostTextEditors.ts", "./vs/workbench/api/node/extHostTypeConverters.ts", "./vs/workbench/api/node/extHostTypes.ts", "./vs/workbench/api/node/extHostUrls.ts", diff --git a/src/vs/workbench/api/node/extHostCLIServer.ts b/src/vs/workbench/api/node/extHostCLIServer.ts index 89f6c02d448..a2311b7f69e 100644 --- a/src/vs/workbench/api/node/extHostCLIServer.ts +++ b/src/vs/workbench/api/node/extHostCLIServer.ts @@ -39,7 +39,7 @@ export class CLIServer { console.error('Could not start open from terminal server.'); } - return this.ipcHandlePath; + return this._ipcHandlePath; } private collectURIToOpen(strs: string[], typeHint: URIType, result: IURIToOpen[]): void { if (Array.isArray(strs)) { diff --git a/src/vs/workbench/api/node/extHostCommands.ts b/src/vs/workbench/api/node/extHostCommands.ts index cc707471087..acf75cefcfb 100644 --- a/src/vs/workbench/api/node/extHostCommands.ts +++ b/src/vs/workbench/api/node/extHostCommands.ts @@ -22,7 +22,7 @@ import { URI } from 'vs/base/common/uri'; interface CommandHandler { callback: Function; thisArg: any; - description: ICommandHandlerDescription; + description?: ICommandHandlerDescription; } export interface ArgumentProcessor { diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index 065e9e61a48..d8a99d2aaee 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -60,7 +60,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic if (didTimeout) { // timeout - no more listeners - return undefined; + return Promise.resolve(); } const document = this._documents.getDocument(resource); diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index 3b316662afb..5e6e2dfb5a1 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -97,6 +97,9 @@ export class ExtHostEditors implements ExtHostEditorsShape { $acceptEditorPropertiesChanged(id: string, data: IEditorPropertiesChangeData): void { const textEditor = this._extHostDocumentsAndEditors.getEditor(id); + if (!textEditor) { + throw new Error('unknown text editor'); + } // (1) set all properties if (data.options) { @@ -137,9 +140,12 @@ export class ExtHostEditors implements ExtHostEditorsShape { } $acceptEditorPositionData(data: ITextEditorPositionData): void { - for (let id in data) { - let textEditor = this._extHostDocumentsAndEditors.getEditor(id); - let viewColumn = TypeConverters.ViewColumn.to(data[id]); + for (const id in data) { + const textEditor = this._extHostDocumentsAndEditors.getEditor(id); + if (!textEditor) { + throw new Error('Unknown text editor'); + } + const viewColumn = TypeConverters.ViewColumn.to(data[id]); if (textEditor.viewColumn !== viewColumn) { textEditor._acceptViewColumn(viewColumn); this._onDidChangeTextEditorViewColumn.fire({ textEditor, viewColumn }); From 8f3cda12e475c810f77c737b590b67b1c7546f1b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 14:49:10 -0800 Subject: [PATCH 126/172] Strict null check extHostFileSystem --- .../workbench/api/node/extHostFileSystem.ts | 82 +++++++++++-------- .../api/node/extHostLanguageFeatures.ts | 4 +- 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/api/node/extHostFileSystem.ts b/src/vs/workbench/api/node/extHostFileSystem.ts index 20f4f98a453..29cf43d41a3 100644 --- a/src/vs/workbench/api/node/extHostFileSystem.ts +++ b/src/vs/workbench/api/node/extHostFileSystem.ts @@ -20,7 +20,7 @@ import { CharCode } from 'vs/base/common/charCode'; class FsLinkProvider { private _schemes: string[] = []; - private _stateMachine: StateMachine; + private _stateMachine?: StateMachine; add(scheme: string): void { this._stateMachine = undefined; @@ -190,6 +190,8 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { case FileChangeType.Deleted: newType = files.FileChangeType.DELETED; break; + default: + throw new Error('Unknown FileChangeType'); } mapped.push({ resource, type: newType }); } @@ -219,60 +221,46 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { return { type, ctime, mtime, size }; } - private _checkProviderExists(handle: number): void { - if (!this._fsProvider.has(handle)) { - const err = new Error(); - err.name = 'ENOPRO'; - err.message = `no provider`; - throw err; - } - } - $stat(handle: number, resource: UriComponents): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat); + return Promise.resolve(this.getProvider(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat); } $readdir(handle: number, resource: UriComponents): Promise<[string, files.FileType][]> { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).readDirectory(URI.revive(resource))); + return Promise.resolve(this.getProvider(handle).readDirectory(URI.revive(resource))); } $readFile(handle: number, resource: UriComponents): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).readFile(URI.revive(resource))).then(data => { + return Promise.resolve(this.getProvider(handle).readFile(URI.revive(resource))).then(data => { return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength); }); } $writeFile(handle: number, resource: UriComponents, content: Buffer, opts: files.FileWriteOptions): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).writeFile(URI.revive(resource), content, opts)); + return Promise.resolve(this.getProvider(handle).writeFile(URI.revive(resource), content, opts)); } $delete(handle: number, resource: UriComponents, opts: files.FileDeleteOptions): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).delete(URI.revive(resource), opts)); + return Promise.resolve(this.getProvider(handle).delete(URI.revive(resource), opts)); } $rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts)); + return Promise.resolve(this.getProvider(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts)); } $copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts)); + const provider = this.getProvider(handle); + if (!provider.copy) { + throw new Error('FileSystemProvider does not implement "copy"'); + } + return Promise.resolve(provider.copy(URI.revive(oldUri), URI.revive(newUri), opts)); } $mkdir(handle: number, resource: UriComponents): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).createDirectory(URI.revive(resource))); + return Promise.resolve(this.getProvider(handle).createDirectory(URI.revive(resource))); } $watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void { - this._checkProviderExists(handle); - let subscription = this._fsProvider.get(handle).watch(URI.revive(resource), opts); + let subscription = this.getProvider(handle).watch(URI.revive(resource), opts); this._watches.set(session, subscription); } @@ -285,26 +273,48 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { } $open(handle: number, resource: UriComponents, opts: files.FileOpenOptions): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).open(URI.revive(resource), opts)); + const provider = this.getProvider(handle); + if (!provider.open) { + throw new Error('FileSystemProvider does not implement "open"'); + } + return Promise.resolve(provider.open(URI.revive(resource), opts)); } $close(handle: number, fd: number): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).close(fd)); + const provider = this.getProvider(handle); + if (!provider.close) { + throw new Error('FileSystemProvider does not implement "close"'); + } + return Promise.resolve(provider.close(fd)); } $read(handle: number, fd: number, pos: number, length: number): Promise { - this._checkProviderExists(handle); + const provider = this.getProvider(handle); + if (!provider.read) { + throw new Error('FileSystemProvider does not implement "read"'); + } const data = Buffer.allocUnsafe(length); - return Promise.resolve(this._fsProvider.get(handle).read(fd, pos, data, 0, length)).then(read => { + return Promise.resolve(provider.read(fd, pos, data, 0, length)).then(read => { return data.slice(0, read); // don't send zeros }); } $write(handle: number, fd: number, pos: number, data: Buffer): Promise { - this._checkProviderExists(handle); - return Promise.resolve(this._fsProvider.get(handle).write(fd, pos, data, 0, data.length)); + const provider = this.getProvider(handle); + if (!provider.write) { + throw new Error('FileSystemProvider does not implement "write"'); + } + return Promise.resolve(provider.write(fd, pos, data, 0, data.length)); } + private getProvider(handle: number): vscode.FileSystemProvider { + const provider = this._fsProvider.get(handle); + if (!provider) { + const err = new Error(); + err.name = 'ENOPRO'; + err.message = `no provider`; + throw err; + } + return provider; + } } diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index b4b5d85a067..54f34709fa2 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -1081,7 +1081,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return Promise.reject(new Error('no adapter found')); } - private _addNewAdapter(adapter: Adapter, extension: IExtensionDescription): number { + private _addNewAdapter(adapter: Adapter, extension: IExtensionDescription | undefined): number { const handle = this._nextHandle(); this._adapter.set(handle, new AdapterData(adapter, extension)); return handle; @@ -1358,7 +1358,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { // --- links - registerDocumentLinkProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { + registerDocumentLinkProvider(extension: IExtensionDescription | undefined, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider), extension); this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); From 14c4fde6d60ef0a0f312ebb6c313a18aee39183a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 15:02:38 -0800 Subject: [PATCH 127/172] Strict null check extHostQuickOpen --- src/tsconfig.strictNullChecks.json | 1 + .../electron-browser/mainThreadQuickOpen.ts | 2 +- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- .../api/node/extHostExtensionService.ts | 3 +++ src/vs/workbench/api/node/extHostQuickOpen.ts | 24 +++++++++++++------ 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index c8f807a4283..2ea5f975449 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -95,6 +95,7 @@ "./vs/workbench/api/node/extHostMessageService.ts", "./vs/workbench/api/node/extHostOutputService.ts", "./vs/workbench/api/node/extHostProgress.ts", + "./vs/workbench/api/node/extHostQuickOpen.ts", "./vs/workbench/api/node/extHostSearch.fileIndex.ts", "./vs/workbench/api/node/extHostSearch.ts", "./vs/workbench/api/node/extHostStorage.ts", diff --git a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts index ab2865d0b32..b9781894eb4 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts @@ -85,7 +85,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape { // ---- input - $input(options: InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise { + $input(options: InputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise { const inputOptions: IInputOptions = Object.create(null); if (options) { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 07a015c08d7..d1568c067e9 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -460,7 +460,7 @@ export interface MainThreadQuickOpenShape extends IDisposable { $show(instance: number, options: IPickOptions, token: CancellationToken): Promise; $setItems(instance: number, items: TransferQuickPickItems[]): Promise; $setError(instance: number, error: Error): Promise; - $input(options: vscode.InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise; + $input(options: vscode.InputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise; $createOrUpdate(params: TransferQuickInput): Promise; $dispose(id: number): Promise; } diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 58ba2e568ef..9eae6df41cf 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -116,6 +116,9 @@ class ExtensionStoragePath { return Promise.resolve(undefined); } + if (!this._environment.appSettingsHome) { + return undefined; + } const storageName = this._workspace.id; const storagePath = path.join(this._environment.appSettingsHome.fsPath, 'workspaceStorage', storageName); diff --git a/src/vs/workbench/api/node/extHostQuickOpen.ts b/src/vs/workbench/api/node/extHostQuickOpen.ts index 7b8dd2432ee..1a8fbce1a76 100644 --- a/src/vs/workbench/api/node/extHostQuickOpen.ts +++ b/src/vs/workbench/api/node/extHostQuickOpen.ts @@ -15,6 +15,7 @@ import { URI } from 'vs/base/common/uri'; import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/node/extHostTypes'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { coalesce } from 'vs/base/common/arrays'; export type Item = string | QuickPickItem; @@ -24,7 +25,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { private _workspace: IExtHostWorkspaceProvider; private _commands: ExtHostCommands; - private _onDidSelectItem: (handle: number) => void; + private _onDidSelectItem?: (handle: number) => void; private _validateInput?: (input: string) => string | undefined | null | Thenable; private _sessions = new Map(); @@ -158,12 +159,15 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { // ---- workspace folder picker - showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise { + showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise { return this._commands.executeCommand('_workbench.pickWorkspaceFolder', [options]).then(async (selectedFolder: WorkspaceFolder) => { if (!selectedFolder) { return undefined; } const workspaceFolders = await this._workspace.getWorkspaceFolders2(); + if (!workspaceFolders) { + return undefined; + } return workspaceFolders.filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0]; }); } @@ -382,7 +386,9 @@ class ExtHostQuickInput implements QuickInput { _fireDidTriggerButton(handle: number) { const button = this._handlesToButtons.get(handle); - this._onDidTriggerButtonEmitter.fire(button); + if (button) { + this._onDidTriggerButtonEmitter.fire(button); + } } _fireDidHide() { @@ -437,9 +443,13 @@ class ExtHostQuickInput implements QuickInput { } } -function getIconUris(iconPath: QuickInputButton['iconPath']) { +function getIconUris(iconPath: QuickInputButton['iconPath']): { dark: URI, light?: URI } | undefined { + const dark = getDarkIconUri(iconPath); const light = getLightIconUri(iconPath); - return { dark: getDarkIconUri(iconPath) || light, light }; + if (!light && !dark) { + return undefined; + } + return { dark: (dark || light)!, light }; } function getLightIconUri(iconPath: QuickInputButton['iconPath']) { @@ -563,13 +573,13 @@ class ExtHostQuickPick extends ExtHostQuickInput implem onDidChangeSelection = this._onDidChangeSelectionEmitter.event; _fireDidChangeActive(handles: number[]) { - const items = handles.map(handle => this._handlesToItems.get(handle)); + const items = coalesce(handles.map(handle => this._handlesToItems.get(handle))); this._activeItems = items; this._onDidChangeActiveEmitter.fire(items); } _fireDidChangeSelection(handles: number[]) { - const items = handles.map(handle => this._handlesToItems.get(handle)); + const items = coalesce(handles.map(handle => this._handlesToItems.get(handle))); this._selectedItems = items; this._onDidChangeSelectionEmitter.fire(items); } From db9a994ded51e3b2e2e15a128cc8dd61fb158171 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 15:08:30 -0800 Subject: [PATCH 128/172] Strict null check extHostDiagnostics --- src/tsconfig.strictNullChecks.json | 1 + src/vs/workbench/api/node/extHost.protocol.ts | 2 +- .../workbench/api/node/extHostDiagnostics.ts | 20 ++++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 2ea5f975449..21cb5fb6cae 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -81,6 +81,7 @@ "./vs/workbench/api/node/extHostCommands.ts", "./vs/workbench/api/node/extHostConfiguration.ts", "./vs/workbench/api/node/extHostDecorations.ts", + "./vs/workbench/api/node/extHostDiagnostics.ts", "./vs/workbench/api/node/extHostDialogs.ts", "./vs/workbench/api/node/extHostDocumentContentProviders.ts", "./vs/workbench/api/node/extHostDocumentData.ts", diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index d1568c067e9..e7cb2b72c07 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -142,7 +142,7 @@ export interface MainThreadConfigurationShape extends IDisposable { } export interface MainThreadDiagnosticsShape extends IDisposable { - $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void; + $changeMany(owner: string, entries: [UriComponents, IMarkerData[] | undefined][]): void; $clear(owner: string): void; } diff --git a/src/vs/workbench/api/node/extHostDiagnostics.ts b/src/vs/workbench/api/node/extHostDiagnostics.ts index e88ae6266c9..fe511a50994 100644 --- a/src/vs/workbench/api/node/extHostDiagnostics.ts +++ b/src/vs/workbench/api/node/extHostDiagnostics.ts @@ -37,7 +37,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { if (!this._isDisposed) { this._onDidChangeDiagnostics.fire(keys(this._data)); this._proxy.$clear(this._owner); - this._data = undefined; + this._data = undefined!; this._isDisposed = true; } } @@ -85,7 +85,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { for (const tuple of first) { const [uri, diagnostics] = tuple; if (!lastUri || uri.toString() !== lastUri.toString()) { - if (lastUri && this._data.get(lastUri.toString()).length === 0) { + if (lastUri && this._data.get(lastUri.toString())!.length === 0) { this._data.delete(lastUri.toString()); } lastUri = uri; @@ -95,9 +95,15 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { if (!diagnostics) { // [Uri, undefined] means clear this - this._data.get(uri.toString()).length = 0; + const currentDiagnostics = this._data.get(uri.toString()); + if (currentDiagnostics) { + currentDiagnostics.length = 0; + } } else { - this._data.get(uri.toString()).push(...diagnostics); + const currentDiagnostics = this._data.get(uri.toString()); + if (currentDiagnostics) { + currentDiagnostics.push(...diagnostics); + } } } } @@ -108,7 +114,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { // compute change and send to main side const entries: [URI, IMarkerData[]][] = []; for (let uri of toSync) { - let marker: IMarkerData[] | undefined; + let marker: IMarkerData[] = []; let diagnostics = this._data.get(uri.toString()); if (diagnostics) { @@ -137,7 +143,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { endColumn: marker[marker.length - 1].endColumn }); } else { - marker = diagnostics.map(converter.Diagnostic.from); + marker = diagnostics.map(diag => converter.Diagnostic.from(diag)); } } @@ -175,7 +181,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { if (Array.isArray(result)) { return Object.freeze(result.slice(0)); } - return undefined; + return []; } has(uri: URI): boolean { From ff1d530157d2db44993269c15ac6ab603fc05fa3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 15:28:08 -0800 Subject: [PATCH 129/172] Strict null work in files/browser --- .../contrib/files/browser/fileActions.ts | 27 ++++++++++++++++--- .../contrib/files/browser/fileCommands.ts | 14 +++++----- .../contrib/files/browser/saveErrorHandler.ts | 4 +-- .../services/editor/common/editorService.ts | 2 +- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 92f15346a27..c8f8f3e9d7b 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -832,7 +832,7 @@ export class ShowActiveFileInExplorer extends Action { } public run(): Promise { - const resource = toResource(this.editorService.activeEditor, { supportSideBySide: true }); + const resource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true }); if (resource) { this.commandService.executeCommand(REVEAL_IN_EXPLORER_COMMAND_ID, resource); } else { @@ -904,7 +904,7 @@ export class ShowOpenedFileInNewWindow extends Action { } public run(): Promise { - const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: true }); + const fileResource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true }); if (fileResource) { if (this.fileService.canHandleResource(fileResource)) { this.windowService.openWindow([{ uri: fileResource, typeHint: 'file' }], { forceNewWindow: true, forceOpenWorkspaceAsFile: true }); @@ -1007,7 +1007,7 @@ export class CompareWithClipboardAction extends Action { } public run(): Promise { - const resource = toResource(this.editorService.activeEditor, { supportSideBySide: true }); + const resource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true }); if (resource && (this.fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) { if (!this.registrationDisposal) { const provider = this.instantiationService.createInstance(ClipboardContentProvider); @@ -1076,7 +1076,7 @@ function openExplorerAndRunAction(accessor: ServicesAccessor, constructor: ICons return explorerPromise.then((explorer: ExplorerViewlet) => { const explorerView = explorer.getExplorerView(); - if (explorerView && explorerView.isBodyVisible()) { + if (explorerView && explorerView.isBodyVisible() && listService.lastFocusedList) { explorerView.focus(); const { stat } = getContext(listService.lastFocusedList); const action = instantationService.createInstance(constructor, () => stat); @@ -1106,6 +1106,10 @@ export const renameHandler = (accessor: ServicesAccessor) => { const listService = accessor.get(IListService); const explorerService = accessor.get(IExplorerService); const textFileService = accessor.get(ITextFileService); + if (!listService.lastFocusedList) { + return; + } + const { stat } = getContext(listService.lastFocusedList); explorerService.setEditable(stat, { @@ -1124,6 +1128,9 @@ export const renameHandler = (accessor: ServicesAccessor) => { export const moveFileToTrashHandler = (accessor: ServicesAccessor) => { const instantationService = accessor.get(IInstantiationService); const listService = accessor.get(IListService); + if (!listService.lastFocusedList) { + return Promise.resolve(); + } const explorerContext = getContext(listService.lastFocusedList); const stats = explorerContext.selection.length > 1 ? explorerContext.selection : [explorerContext.stat]; @@ -1134,6 +1141,9 @@ export const moveFileToTrashHandler = (accessor: ServicesAccessor) => { export const deleteFileHandler = (accessor: ServicesAccessor) => { const instantationService = accessor.get(IInstantiationService); const listService = accessor.get(IListService); + if (!listService.lastFocusedList) { + return Promise.resolve(); + } const explorerContext = getContext(listService.lastFocusedList); const stats = explorerContext.selection.length > 1 ? explorerContext.selection : [explorerContext.stat]; @@ -1143,6 +1153,9 @@ export const deleteFileHandler = (accessor: ServicesAccessor) => { export const copyFileHandler = (accessor: ServicesAccessor) => { const listService = accessor.get(IListService); + if (!listService.lastFocusedList) { + return; + } const explorerContext = getContext(listService.lastFocusedList); const explorerService = accessor.get(IExplorerService); const stats = explorerContext.selection.length > 1 ? explorerContext.selection : [explorerContext.stat]; @@ -1152,6 +1165,9 @@ export const copyFileHandler = (accessor: ServicesAccessor) => { export const cutFileHandler = (accessor: ServicesAccessor) => { const listService = accessor.get(IListService); + if (!listService.lastFocusedList) { + return; + } const explorerContext = getContext(listService.lastFocusedList); const explorerService = accessor.get(IExplorerService); const stats = explorerContext.selection.length > 1 ? explorerContext.selection : [explorerContext.stat]; @@ -1163,6 +1179,9 @@ export const pasteFileHandler = (accessor: ServicesAccessor) => { const instantationService = accessor.get(IInstantiationService); const listService = accessor.get(IListService); const clipboardService = accessor.get(IClipboardService); + if (!listService.lastFocusedList) { + return Promise.resolve(); + } const explorerContext = getContext(listService.lastFocusedList); return sequence(resources.distinctParents(clipboardService.readResources(), r => r).map(toCopy => { diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 136bbc9d387..d5483f119d8 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -111,7 +111,7 @@ function save( // Save As (or Save untitled with associated path) if (isSaveAs || resource.scheme === Schemas.untitled) { - let encodingOfSource: string; + let encodingOfSource: string | undefined; if (resource.scheme === Schemas.untitled) { encodingOfSource = untitledEditorService.getEncoding(resource); } else if (fileService.canHandleResource(resource)) { @@ -119,17 +119,17 @@ function save( encodingOfSource = textModel && textModel.getEncoding(); // text model can be null e.g. if this is a binary file! } - let viewStateOfSource: IEditorViewState; + let viewStateOfSource: IEditorViewState | null; const activeTextEditorWidget = getCodeEditor(editorService.activeTextEditorWidget); if (activeTextEditorWidget) { - const activeResource = toResource(editorService.activeEditor, { supportSideBySide: true }); + const activeResource = toResource(editorService.activeEditor || null, { supportSideBySide: true }); if (activeResource && (fileService.canHandleResource(activeResource) || resource.scheme === Schemas.untitled) && activeResource.toString() === resource.toString()) { viewStateOfSource = activeTextEditorWidget.saveViewState(); } } // Special case: an untitled file with associated path gets saved directly unless "saveAs" is true - let savePromise: Promise; + let savePromise: Promise; if (!isSaveAs && resource.scheme === Schemas.untitled && untitledEditorService.hasAssociatedFilePath(resource)) { savePromise = textFileService.save(resource, options).then((result) => { if (result) { @@ -152,7 +152,7 @@ function save( return savePromise.then((target) => { if (!target || target.toString() === resource.toString()) { - return undefined; // save canceled or same resource used + return false; // save canceled or same resource used } const replacement: IResourceInput = { @@ -175,7 +175,7 @@ function save( // Pin the active editor if we are saving it const activeControl = editorService.activeControl; const activeEditorResource = activeControl && activeControl.input && activeControl.input.getResource(); - if (activeEditorResource && activeEditorResource.toString() === resource.toString()) { + if (activeControl && activeEditorResource && activeEditorResource.toString() === resource.toString()) { activeControl.group.pinEditor(activeControl.input); } @@ -203,7 +203,7 @@ function saveAll(saveAllArguments: any, editorService: IEditorService, untitledE groupIdToUntitledResourceInput.set(g.id, []); } - groupIdToUntitledResourceInput.get(g.id).push({ + groupIdToUntitledResourceInput.get(g.id)!.push({ encoding: untitledEditorService.getEncoding(resource), resource, options: { diff --git a/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts b/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts index c3861633546..2da2752ef21 100644 --- a/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts +++ b/src/vs/workbench/contrib/files/browser/saveErrorHandler.ts @@ -9,7 +9,7 @@ import { basename } from 'vs/base/common/resources'; import { Action } from 'vs/base/common/actions'; import { URI } from 'vs/base/common/uri'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; -import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -321,7 +321,7 @@ export const acceptLocalChangesCommand = (accessor: ServicesAccessor, resource: const group = control.group; resolverService.createModelReference(resource).then(reference => { - const model = reference.object as ITextFileEditorModel; + const model = reference.object as IResolvedTextFileEditorModel; const localModelSnapshot = model.createSnapshot(); clearPendingResolveSaveConflictMessages(); // hide any previously shown message about how to use these actions diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index a0f2e0006a1..e9b88ee2c46 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -36,7 +36,7 @@ export interface IOpenEditorOverride { * If defined, will prevent the opening of an editor and replace the resulting * promise with the provided promise for the openEditor() call. */ - override?: Promise; + override?: Promise; } export interface IActiveEditor extends IEditor { From aef80e8070182c81cacf01a68eaff1731fb67b30 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 16:07:58 -0800 Subject: [PATCH 130/172] Auto marking fields as readonly in mainThread files --- .../electron-browser/mainThreadComments.ts | 22 ++++++++-------- .../mainThreadDebugService.ts | 14 +++++----- .../electron-browser/mainThreadDecorations.ts | 2 +- .../electron-browser/mainThreadDocuments.ts | 18 ++++++------- .../mainThreadDocumentsAndEditors.ts | 4 +-- .../api/electron-browser/mainThreadEditor.ts | 6 ++--- .../api/electron-browser/mainThreadEditors.ts | 6 ++--- .../electron-browser/mainThreadHeapService.ts | 2 +- .../mainThreadLanguageFeatures.ts | 8 +++--- .../mainThreadOutputService.ts | 2 +- .../electron-browser/mainThreadProgress.ts | 4 +-- .../electron-browser/mainThreadQuickOpen.ts | 6 ++--- .../api/electron-browser/mainThreadSCM.ts | 26 +++++++++---------- .../mainThreadSaveParticipant.ts | 2 +- .../api/electron-browser/mainThreadStorage.ts | 8 +++--- .../api/electron-browser/mainThreadTask.ts | 6 ++--- .../electron-browser/mainThreadTreeViews.ts | 12 ++++----- 17 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadComments.ts b/src/vs/workbench/api/electron-browser/mainThreadComments.ts index ebbe7023a9a..0c50eeb40ea 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadComments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadComments.ts @@ -26,9 +26,9 @@ import { IRange } from 'vs/editor/common/core/range'; import { Emitter, Event } from 'vs/base/common/event'; export class MainThreadDocumentCommentProvider implements modes.DocumentCommentProvider { - private _proxy: ExtHostCommentsShape; - private _handle: number; - private _features: CommentProviderFeatures; + private readonly _proxy: ExtHostCommentsShape; + private readonly _handle: number; + private readonly _features: CommentProviderFeatures; get startDraftLabel(): string | undefined { return this._features.startDraftLabel; } get deleteDraftLabel(): string | undefined { return this._features.deleteDraftLabel; } get finishDraftLabel(): string | undefined { return this._features.finishDraftLabel; } @@ -197,14 +197,14 @@ export class MainThreadCommentControl { return this._label; } - private _threads: Map = new Map(); - private _commentingRanges: Map = new Map(); + private readonly _threads: Map = new Map(); + private readonly _commentingRanges: Map = new Map(); constructor( - private _proxy: ExtHostCommentsShape, - private _commentService: ICommentService, - private _handle: number, - private _id: string, - private _label: string + private readonly _proxy: ExtHostCommentsShape, + private readonly _commentService: ICommentService, + private readonly _handle: number, + private readonly _id: string, + private readonly _label: string ) { } createCommentThread(commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, comments: modes.Comment[], commands: modes.Command[], collapseState: modes.CommentThreadCollapsibleState): modes.CommentThread2 { @@ -331,7 +331,7 @@ export class MainThreadCommentControl { export class MainThreadComments extends Disposable implements MainThreadCommentsShape { private _disposables: IDisposable[]; private _activeCommentThreadDisposables: IDisposable[]; - private _proxy: ExtHostCommentsShape; + private readonly _proxy: ExtHostCommentsShape; private _documentProviders = new Map(); private _workspaceProviders = new Map(); private _handlers = new Map(); diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index 395c6b87b0e..fe7631d0a0e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -19,15 +19,15 @@ import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/contrib/debug/ @extHostNamedCustomer(MainContext.MainThreadDebugService) export class MainThreadDebugService implements MainThreadDebugServiceShape, IDebugAdapterFactory { - private _proxy: ExtHostDebugServiceShape; + private readonly _proxy: ExtHostDebugServiceShape; private _toDispose: IDisposable[]; private _breakpointEventsActive: boolean; - private _debugAdapters: Map; + private readonly _debugAdapters: Map; private _debugAdaptersHandleCounter = 1; - private _debugConfigurationProviders: Map; - private _debugAdapterDescriptorFactories: Map; - private _debugAdapterTrackerFactories: Map; - private _sessions: Set; + private readonly _debugConfigurationProviders: Map; + private readonly _debugAdapterDescriptorFactories: Map; + private readonly _debugAdapterTrackerFactories: Map; + private readonly _sessions: Set; constructor( extHostContext: IExtHostContext, @@ -343,7 +343,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb */ class ExtensionHostDebugAdapter extends AbstractDebugAdapter { - constructor(private _ds: MainThreadDebugService, private _handle: number, private _proxy: ExtHostDebugServiceShape, private _session: IDebugSession) { + constructor(private readonly _ds: MainThreadDebugService, private _handle: number, private _proxy: ExtHostDebugServiceShape, private _session: IDebugSession) { super(); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts index 8847d97283a..84281c3a6c2 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -21,7 +21,7 @@ class DecorationRequestsQueue { private _timer: any; constructor( - private _proxy: ExtHostDecorationsShape + private readonly _proxy: ExtHostDecorationsShape ) { // } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts index 7780708d837..ac7e79434ed 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts @@ -24,8 +24,8 @@ export class BoundModelReferenceCollection { private _length = 0; constructor( - private _maxAge: number = 1000 * 60 * 3, - private _maxLength: number = 1024 * 1024 * 80 + private readonly _maxAge: number = 1000 * 60 * 3, + private readonly _maxLength: number = 1024 * 1024 * 80 ) { // } @@ -64,16 +64,16 @@ export class BoundModelReferenceCollection { export class MainThreadDocuments implements MainThreadDocumentsShape { - private _modelService: IModelService; - private _textModelResolverService: ITextModelService; - private _textFileService: ITextFileService; - private _fileService: IFileService; - private _untitledEditorService: IUntitledEditorService; + private readonly _modelService: IModelService; + private readonly _textModelResolverService: ITextModelService; + private readonly _textFileService: ITextFileService; + private readonly _fileService: IFileService; + private readonly _untitledEditorService: IUntitledEditorService; private _toDispose: IDisposable[]; private _modelToDisposeMap: { [modelUrl: string]: IDisposable; }; - private _proxy: ExtHostDocumentsShape; - private _modelIsSynced: { [modelId: string]: boolean; }; + private readonly _proxy: ExtHostDocumentsShape; + private readonly _modelIsSynced: { [modelId: string]: boolean; }; private _modelReferenceCollection = new BoundModelReferenceCollection(); constructor( diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts index dd73c36be3f..eef961784b7 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts @@ -304,8 +304,8 @@ class MainThreadDocumentAndEditorStateComputer { export class MainThreadDocumentsAndEditors { private _toDispose: IDisposable[]; - private _proxy: ExtHostDocumentsAndEditorsShape; - private _stateComputer: MainThreadDocumentAndEditorStateComputer; + private readonly _proxy: ExtHostDocumentsAndEditorsShape; + private readonly _stateComputer: MainThreadDocumentAndEditorStateComputer; private _textEditors = <{ [id: string]: MainThreadTextEditor }>Object.create(null); private _onTextEditorAdd = new Emitter(); diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts index 30639a78a94..7e221b1b5da 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts @@ -181,12 +181,12 @@ export class MainThreadTextEditorProperties { */ export class MainThreadTextEditor { - private _id: string; + private readonly _id: string; private _model: ITextModel; - private _modelService: IModelService; + private readonly _modelService: IModelService; private _modelListeners: IDisposable[]; private _codeEditor: ICodeEditor | null; - private _focusTracker: IFocusTracker; + private readonly _focusTracker: IFocusTracker; private _codeEditorListeners: IDisposable[]; private _properties: MainThreadTextEditorProperties; diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index bd1a7845c05..6e49573d76e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -31,9 +31,9 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { private static INSTANCE_COUNT: number = 0; - private _instanceId: string; - private _proxy: ExtHostEditorsShape; - private _documentsAndEditors: MainThreadDocumentsAndEditors; + private readonly _instanceId: string; + private readonly _proxy: ExtHostEditorsShape; + private readonly _documentsAndEditors: MainThreadDocumentsAndEditors; private _toDispose: IDisposable[]; private _textEditorsListenersMap: { [editorId: string]: IDisposable[]; }; private _editorPositionData: ITextEditorPositionData | null; diff --git a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts index 1b5d15ee21c..486a290b705 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts @@ -96,7 +96,7 @@ export class HeapService implements IHeapService { @extHostCustomer export class MainThreadHeapService { - private _toDispose: IDisposable; + private readonly _toDispose: IDisposable; constructor( extHostContext: IExtHostContext, diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 0be7720a10f..8abeedd7878 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -26,10 +26,10 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; @extHostNamedCustomer(MainContext.MainThreadLanguageFeatures) export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape { - private _proxy: ExtHostLanguageFeaturesShape; - private _heapService: IHeapService; - private _modeService: IModeService; - private _registrations: { [handle: number]: IDisposable; } = Object.create(null); + private readonly _proxy: ExtHostLanguageFeaturesShape; + private readonly _heapService: IHeapService; + private readonly _modeService: IModeService; + private readonly _registrations: { [handle: number]: IDisposable; } = Object.create(null); constructor( extHostContext: IExtHostContext, diff --git a/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts b/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts index 9665fd33072..7c0308b8bdb 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts @@ -18,7 +18,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut private static _idPool = 1; - private _proxy: ExtHostOutputServiceShape; + private readonly _proxy: ExtHostOutputServiceShape; private readonly _outputService: IOutputService; private readonly _partService: IPartService; private readonly _panelService: IPanelService; diff --git a/src/vs/workbench/api/electron-browser/mainThreadProgress.ts b/src/vs/workbench/api/electron-browser/mainThreadProgress.ts index 5521d8f3854..80944a23128 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadProgress.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadProgress.ts @@ -10,9 +10,9 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC @extHostNamedCustomer(MainContext.MainThreadProgress) export class MainThreadProgress implements MainThreadProgressShape { - private _progressService: IProgressService2; + private readonly _progressService: IProgressService2; private _progress = new Map void, progress: IProgress }>(); - private _proxy: ExtHostProgressShape; + private readonly _proxy: ExtHostProgressShape; constructor( extHostContext: IExtHostContext, diff --git a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts index b9781894eb4..976b27dc76d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts @@ -18,9 +18,9 @@ interface QuickInputSession { @extHostNamedCustomer(MainContext.MainThreadQuickOpen) export class MainThreadQuickOpen implements MainThreadQuickOpenShape { - private _proxy: ExtHostQuickOpenShape; - private _quickInputService: IQuickInputService; - private _items: Record = {}; diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 667110d3612..094700da329 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -27,8 +27,8 @@ class MainThreadSCMResourceGroup implements ISCMResourceGroup { get onDidChange(): Event { return this._onDidChange.event; } constructor( - private sourceControlHandle: number, - private handle: number, + private readonly sourceControlHandle: number, + private readonly handle: number, public provider: ISCMProvider, public features: SCMGroupFeatures, public label: string, @@ -62,10 +62,10 @@ class MainThreadSCMResourceGroup implements ISCMResourceGroup { class MainThreadSCMResource implements ISCMResource { constructor( - private proxy: ExtHostSCMShape, - private sourceControlHandle: number, - private groupHandle: number, - private handle: number, + private readonly proxy: ExtHostSCMShape, + private readonly sourceControlHandle: number, + private readonly groupHandle: number, + private readonly handle: number, public sourceUri: URI, public resourceGroup: ISCMResourceGroup, public decorations: ISCMResourceDecorations @@ -92,7 +92,7 @@ class MainThreadSCMProvider implements ISCMProvider { get id(): string { return this._id; } readonly groups = new Sequence(); - private _groupsByHandle: { [handle: number]: MainThreadSCMResourceGroup; } = Object.create(null); + private readonly _groupsByHandle: { [handle: number]: MainThreadSCMResourceGroup; } = Object.create(null); // get groups(): ISequence { // return { @@ -129,11 +129,11 @@ class MainThreadSCMProvider implements ISCMProvider { get onDidChange(): Event { return this._onDidChange.event; } constructor( - private proxy: ExtHostSCMShape, - private _handle: number, - private _contextValue: string, - private _label: string, - private _rootUri: URI | undefined, + private readonly proxy: ExtHostSCMShape, + private readonly _handle: number, + private readonly _contextValue: string, + private readonly _label: string, + private readonly _rootUri: URI | undefined, @ISCMService scmService: ISCMService ) { } @@ -265,7 +265,7 @@ class MainThreadSCMProvider implements ISCMProvider { @extHostNamedCustomer(MainContext.MainThreadSCM) export class MainThreadSCM implements MainThreadSCMShape { - private _proxy: ExtHostSCMShape; + private readonly _proxy: ExtHostSCMShape; private _repositories: { [handle: number]: ISCMRepository; } = Object.create(null); private _inputDisposables: { [handle: number]: IDisposable; } = Object.create(null); private _disposables: IDisposable[] = []; diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 32c7b8403af..e098327460d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -367,7 +367,7 @@ class CodeActionOnSaveParticipant implements ISaveParticipant { class ExtHostSaveParticipant implements ISaveParticipantParticipant { - private _proxy: ExtHostDocumentSaveParticipantShape; + private readonly _proxy: ExtHostDocumentSaveParticipantShape; constructor(extHostContext: IExtHostContext) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant); diff --git a/src/vs/workbench/api/electron-browser/mainThreadStorage.ts b/src/vs/workbench/api/electron-browser/mainThreadStorage.ts index 96f63fbecba..455cdbcf11e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadStorage.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadStorage.ts @@ -11,10 +11,10 @@ import { IDisposable } from 'vs/base/common/lifecycle'; @extHostNamedCustomer(MainContext.MainThreadStorage) export class MainThreadStorage implements MainThreadStorageShape { - private _storageService: IStorageService; - private _proxy: ExtHostStorageShape; - private _storageListener: IDisposable; - private _sharedStorageKeysToWatch: Map = new Map(); + private readonly _storageService: IStorageService; + private readonly _proxy: ExtHostStorageShape; + private readonly _storageListener: IDisposable; + private readonly _sharedStorageKeysToWatch: Map = new Map(); constructor( extHostContext: IExtHostContext, diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index 985a5df8556..a769f84ab75 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -382,9 +382,9 @@ namespace TaskFilterDTO { @extHostNamedCustomer(MainContext.MainThreadTask) export class MainThreadTask implements MainThreadTaskShape { - private _extHostContext: IExtHostContext; - private _proxy: ExtHostTaskShape; - private _providers: Map; + private readonly _extHostContext: IExtHostContext; + private readonly _proxy: ExtHostTaskShape; + private readonly _providers: Map; constructor( extHostContext: IExtHostContext, diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts index 2d6da3314f5..fe4995feb35 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts @@ -15,8 +15,8 @@ import { IMarkdownString } from 'vs/base/common/htmlContent'; @extHostNamedCustomer(MainContext.MainThreadTreeViews) export class MainThreadTreeViews extends Disposable implements MainThreadTreeViewsShape { - private _proxy: ExtHostTreeViewsShape; - private _dataProviders: Map = new Map(); + private readonly _proxy: ExtHostTreeViewsShape; + private readonly _dataProviders: Map = new Map(); constructor( extHostContext: IExtHostContext, @@ -133,11 +133,11 @@ type TreeItemHandle = string; class TreeViewDataProvider implements ITreeViewDataProvider { - private itemsMap: Map = new Map(); + private readonly itemsMap: Map = new Map(); - constructor(private treeViewId: string, - private _proxy: ExtHostTreeViewsShape, - private notificationService: INotificationService + constructor(private readonly treeViewId: string, + private readonly _proxy: ExtHostTreeViewsShape, + private readonly notificationService: INotificationService ) { } From 52556f97425ffbec3b8ba68de0ce8be70b5df167 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 16:25:26 -0800 Subject: [PATCH 131/172] Auto converting `let` -> `const` where possible in mainthread and extHost Const provides better type guards and can make logic clearer --- .../electron-browser/mainThreadCommands.ts | 2 +- .../electron-browser/mainThreadDocuments.ts | 12 ++-- .../mainThreadDocumentsAndEditors.ts | 8 +-- .../api/electron-browser/mainThreadEditor.ts | 12 ++-- .../api/electron-browser/mainThreadEditors.ts | 16 ++--- .../mainThreadFileSystemEventService.ts | 2 +- .../mainThreadLanguageFeatures.ts | 6 +- .../electron-browser/mainThreadLanguages.ts | 2 +- .../mainThreadMessageService.ts | 2 +- .../mainThreadSaveParticipant.ts | 4 +- .../electron-browser/mainThreadStatusBar.ts | 4 +- .../api/electron-browser/mainThreadStorage.ts | 4 +- .../api/electron-browser/mainThreadTask.ts | 62 +++++++++---------- src/vs/workbench/api/node/extHost.api.impl.ts | 8 +-- .../workbench/api/node/extHostApiCommands.ts | 6 +- src/vs/workbench/api/node/extHostCommands.ts | 2 +- src/vs/workbench/api/node/extHostComments.ts | 4 +- .../workbench/api/node/extHostDebugService.ts | 22 +++---- .../workbench/api/node/extHostDiagnostics.ts | 14 ++--- .../workbench/api/node/extHostDocumentData.ts | 18 +++--- .../node/extHostDocumentSaveParticipant.ts | 2 +- src/vs/workbench/api/node/extHostDocuments.ts | 2 +- .../api/node/extHostExtensionActivator.ts | 10 +-- .../api/node/extHostExtensionService.ts | 18 +++--- .../workbench/api/node/extHostFileSystem.ts | 10 +-- .../api/node/extHostFileSystemEventService.ts | 10 +-- .../api/node/extHostLanguageFeatures.ts | 38 ++++++------ .../api/node/extHostMessageService.ts | 4 +- src/vs/workbench/api/node/extHostQuickOpen.ts | 4 +- .../api/node/extHostSearch.fileIndex.ts | 6 +- src/vs/workbench/api/node/extHostStatusBar.ts | 4 +- src/vs/workbench/api/node/extHostTask.ts | 48 +++++++------- .../workbench/api/node/extHostTextEditor.ts | 34 +++++----- .../workbench/api/node/extHostTextEditors.ts | 2 +- src/vs/workbench/api/node/extHostTreeViews.ts | 8 +-- .../api/node/extHostTypeConverters.ts | 4 +- src/vs/workbench/api/node/extHostTypes.ts | 22 +++---- src/vs/workbench/api/node/extHostWorkspace.ts | 2 +- 38 files changed, 219 insertions(+), 219 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadCommands.ts b/src/vs/workbench/api/electron-browser/mainThreadCommands.ts index 061034039c1..4e8d426c589 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadCommands.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadCommands.ts @@ -89,7 +89,7 @@ function _generateMarkdown(description: string | ICommandHandlerDescription): st if (typeof description === 'string') { return description; } else { - let parts = [description.description]; + const parts = [description.description]; parts.push('\n\n'); if (description.args) { for (let arg of description.args) { diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts index ac7e79434ed..651d521c3a8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts @@ -35,11 +35,11 @@ export class BoundModelReferenceCollection { } add(ref: IReference): void { - let length = ref.object.textEditorModel.getValueLength(); + const length = ref.object.textEditorModel.getValueLength(); let handle: any; let entry: { length: number, dispose(): void }; const dispose = () => { - let idx = this._data.indexOf(entry); + const idx = this._data.indexOf(entry); if (idx >= 0) { this._length -= length; ref.dispose(); @@ -139,7 +139,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { // don't synchronize too large models return; } - let modelUrl = model.uri; + const modelUrl = model.uri; this._modelIsSynced[modelUrl.toString()] = true; this._modelToDisposeMap[modelUrl.toString()] = model.onDidChangeContent((e) => { this._proxy.$acceptModelChanged(modelUrl, e, this._textFileService.isDirty(modelUrl)); @@ -148,7 +148,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { private _onModelModeChanged(event: { model: ITextModel; oldModeId: string; }): void { let { model, oldModeId } = event; - let modelUrl = model.uri; + const modelUrl = model.uri; if (!this._modelIsSynced[modelUrl.toString()]) { return; } @@ -156,7 +156,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { } private _onModelRemoved(modelUrl: URI): void { - let strModelUrl = modelUrl.toString(); + const strModelUrl = modelUrl.toString(); if (!this._modelIsSynced[strModelUrl]) { return; } @@ -214,7 +214,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { } private _handleUntitledScheme(uri: URI): Promise { - let asFileUri = uri.with({ scheme: Schemas.file }); + const asFileUri = uri.with({ scheme: Schemas.file }); return this._fileService.resolveFile(asFileUri).then(stats => { // don't create a new file ontop of an existing file return Promise.reject(new Error('file already exists on disk')); diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts index eef961784b7..18e432e32de 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts @@ -283,7 +283,7 @@ class MainThreadDocumentAndEditorStateComputer { } private _getActiveEditorFromPanel(): IEditor | undefined { - let panel = this._panelService.getActivePanel(); + const panel = this._panelService.getActivePanel(); if (panel instanceof BaseTextEditor && isCodeEditor(panel.getControl())) { return panel.getControl(); } else { @@ -362,8 +362,8 @@ export class MainThreadDocumentsAndEditors { private _onDelta(delta: DocumentAndEditorStateDelta): void { let removedDocuments: URI[]; - let removedEditors: string[] = []; - let addedEditors: MainThreadTextEditor[] = []; + const removedEditors: string[] = []; + const addedEditors: MainThreadTextEditor[] = []; // removed models removedDocuments = delta.removedDocuments.map(m => m.uri); @@ -387,7 +387,7 @@ export class MainThreadDocumentsAndEditors { } } - let extHostDelta: IDocumentsAndEditorsDelta = Object.create(null); + const extHostDelta: IDocumentsAndEditorsDelta = Object.create(null); let empty = true; if (delta.newActiveEditor !== undefined) { empty = false; diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts index 7e221b1b5da..1ae5dcb8ee7 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts @@ -105,7 +105,7 @@ export class MainThreadTextEditorProperties { } public generateDelta(oldProps: MainThreadTextEditorProperties | null, selectionChangeSource: string | null): IEditorPropertiesChangeData | null { - let delta: IEditorPropertiesChangeData = { + const delta: IEditorPropertiesChangeData = { options: null, selections: null, visibleRanges: null @@ -323,7 +323,7 @@ export class MainThreadTextEditor { } private _setIndentConfiguration(newConfiguration: ITextEditorConfigurationUpdate): void { - let creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri, this._model.isForSimpleWidget); + const creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri, this._model.isForSimpleWidget); if (newConfiguration.tabSize === 'auto' || newConfiguration.insertSpaces === 'auto') { // one of the options was set to 'auto' => detect indentation @@ -342,7 +342,7 @@ export class MainThreadTextEditor { return; } - let newOpts: ITextModelUpdateOptions = {}; + const newOpts: ITextModelUpdateOptions = {}; if (typeof newConfiguration.insertSpaces !== 'undefined') { newOpts.insertSpaces = newConfiguration.insertSpaces; } @@ -367,7 +367,7 @@ export class MainThreadTextEditor { } if (newConfiguration.cursorStyle) { - let newCursorStyle = cursorStyleToString(newConfiguration.cursorStyle); + const newCursorStyle = cursorStyleToString(newConfiguration.cursorStyle); this._codeEditor.updateOptions({ cursorStyle: newCursorStyle }); @@ -402,7 +402,7 @@ export class MainThreadTextEditor { if (!this._codeEditor) { return; } - let ranges: Range[] = []; + const ranges: Range[] = []; for (let i = 0, len = Math.floor(_ranges.length / 4); i < len; i++) { ranges[i] = new Range(_ranges[4 * i], _ranges[4 * i + 1], _ranges[4 * i + 2], _ranges[4 * i + 3]); } @@ -464,7 +464,7 @@ export class MainThreadTextEditor { this._model.pushEOL(EndOfLineSequence.LF); } - let transformedEdits = edits.map((edit): IIdentifiedSingleEditOperation => { + const transformedEdits = edits.map((edit): IIdentifiedSingleEditOperation => { return { range: Range.lift(edit.range), text: edit.text, diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index 6e49573d76e..d1d7e1cd812 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -77,8 +77,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { } private _onTextEditorAdd(textEditor: MainThreadTextEditor): void { - let id = textEditor.getId(); - let toDispose: IDisposable[] = []; + const id = textEditor.getId(); + const toDispose: IDisposable[] = []; toDispose.push(textEditor.onPropertiesChanged((data) => { this._proxy.$acceptEditorPropertiesChanged(id, data); })); @@ -94,7 +94,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { private _updateActiveAndVisibleTextEditors(): void { // editor columns - let editorPositionData = this._getTextEditorPositionData(); + const editorPositionData = this._getTextEditorPositionData(); if (!objectEquals(this._editorPositionData, editorPositionData)) { this._editorPositionData = editorPositionData; this._proxy.$acceptEditorPositionData(this._editorPositionData); @@ -102,7 +102,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { } private _getTextEditorPositionData(): ITextEditorPositionData { - let result: ITextEditorPositionData = Object.create(null); + const result: ITextEditorPositionData = Object.create(null); for (let workbenchEditor of this._editorService.visibleControls) { const id = this._documentsAndEditors.findTextEditorIdFor(workbenchEditor); if (id) { @@ -137,9 +137,9 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { } $tryShowEditor(id: string, position?: EditorViewColumn): Promise { - let mainThreadEditor = this._documentsAndEditors.getEditor(id); + const mainThreadEditor = this._documentsAndEditors.getEditor(id); if (mainThreadEditor) { - let model = mainThreadEditor.getModel(); + const model = mainThreadEditor.getModel(); return this._editorService.openEditor({ resource: model.uri, options: { preserveFocus: false } @@ -149,9 +149,9 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { } $tryHideEditor(id: string): Promise { - let mainThreadEditor = this._documentsAndEditors.getEditor(id); + const mainThreadEditor = this._documentsAndEditors.getEditor(id); if (mainThreadEditor) { - let editors = this._editorService.visibleControls; + const editors = this._editorService.visibleControls; for (let editor of editors) { if (mainThreadEditor.matches(editor)) { return editor.group.closeEditor(editor.input).then(() => { return; }); diff --git a/src/vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts index 1e9d568863e..351edd07f6d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts @@ -57,7 +57,7 @@ export class MainThreadFileSystemEventService { }, undefined, this._listener); textfileService.onWillMove(e => { - let promise = proxy.$onWillRename(e.oldResource, e.newResource); + const promise = proxy.$onWillRename(e.oldResource, e.newResource); e.waitUntil(promise); }, undefined, this._listener); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 8abeedd7878..3de39e6a654 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -48,7 +48,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } $unregister(handle: number): void { - let registration = this._registrations[handle]; + const registration = this._registrations[handle]; if (registration) { registration.dispose(); delete this._registrations[handle]; @@ -506,7 +506,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $setLanguageConfiguration(handle: number, languageId: string, _configuration: ISerializedLanguageConfiguration): void { - let configuration: LanguageConfiguration = { + const configuration: LanguageConfiguration = { comments: _configuration.comments, brackets: _configuration.brackets, wordPattern: MainThreadLanguageFeatures._reviveRegExp(_configuration.wordPattern), @@ -532,7 +532,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }; } - let languageIdentifier = this._modeService.getLanguageIdentifier(languageId); + const languageIdentifier = this._modeService.getLanguageIdentifier(languageId); if (languageIdentifier) { this._registrations[handle] = LanguageConfigurationRegistry.register(languageIdentifier, configuration); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts index 88925d6bceb..392903a9e16 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts @@ -29,7 +29,7 @@ export class MainThreadLanguages implements MainThreadLanguagesShape { $changeLanguage(resource: UriComponents, languageId: string): Promise { const uri = URI.revive(resource); - let model = this._modelService.getModel(uri); + const model = this._modelService.getModel(uri); if (!model) { return Promise.reject(new Error('Invalid uri')); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts b/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts index 68cf1ff4c04..be0157d8b5f 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts @@ -44,7 +44,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { return new Promise(resolve => { - let primaryActions: MessageItemAction[] = []; + const primaryActions: MessageItemAction[] = []; class MessageItemAction extends Action { constructor(id: string, label: string, handle: number) { diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index e098327460d..fd647ecfe68 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -235,8 +235,8 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { const timeout = this._configurationService.getValue('editor.formatOnSaveTimeout', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() }); return new Promise((resolve, reject) => { - let source = new CancellationTokenSource(); - let request = getDocumentFormattingEdits(this._telemetryService, this._editorWorkerService, model, model.getFormattingOptions(), FormatMode.Auto, source.token); + const source = new CancellationTokenSource(); + const request = getDocumentFormattingEdits(this._telemetryService, this._editorWorkerService, model, model.getFormattingOptions(), FormatMode.Auto, source.token); setTimeout(() => { reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout)); diff --git a/src/vs/workbench/api/electron-browser/mainThreadStatusBar.ts b/src/vs/workbench/api/electron-browser/mainThreadStatusBar.ts index f002ffb6889..e6f2d2f3635 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadStatusBar.ts @@ -34,12 +34,12 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this.$dispose(id); // Add new - let entry = this._statusbarService.addEntry({ text, tooltip, command, color, extensionId }, alignment, priority); + const entry = this._statusbarService.addEntry({ text, tooltip, command, color, extensionId }, alignment, priority); this._entries[id] = entry; } $dispose(id: number) { - let disposeable = this._entries[id]; + const disposeable = this._entries[id]; if (disposeable) { disposeable.dispose(); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadStorage.ts b/src/vs/workbench/api/electron-browser/mainThreadStorage.ts index 455cdbcf11e..04aae06d817 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadStorage.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadStorage.ts @@ -24,7 +24,7 @@ export class MainThreadStorage implements MainThreadStorageShape { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostStorage); this._storageListener = this._storageService.onDidChangeStorage(e => { - let shared = e.scope === StorageScope.GLOBAL; + const shared = e.scope === StorageScope.GLOBAL; if (shared && this._sharedStorageKeysToWatch.has(e.key)) { try { this._proxy.$acceptValue(shared, e.key, this._getValue(shared, e.key)); @@ -51,7 +51,7 @@ export class MainThreadStorage implements MainThreadStorageShape { } private _getValue(shared: boolean, key: string): T | undefined { - let jsonValue = this._storageService.get(key, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE); + const jsonValue = this._storageService.get(key, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE); if (!jsonValue) { return undefined; } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index a769f84ab75..47bc0be5ea3 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -70,7 +70,7 @@ namespace TaskProcessEndedDTO { namespace TaskDefinitionDTO { export function from(value: KeyedTaskIdentifier): TaskDefinitionDTO { - let result = Objects.assign(Object.create(null), value); + const result = Objects.assign(Object.create(null), value); delete result._key; return result; } @@ -139,13 +139,13 @@ namespace ProcessExecutionOptionsDTO { namespace ProcessExecutionDTO { export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO { - let candidate = value as ProcessExecutionDTO; + const candidate = value as ProcessExecutionDTO; return candidate && !!candidate.process; } export function from(value: CommandConfiguration): ProcessExecutionDTO { - let process: string = Types.isString(value.name) ? value.name : value.name.value; - let args: string[] = value.args ? value.args.map(value => Types.isString(value) ? value : value.value) : []; - let result: ProcessExecutionDTO = { + const process: string = Types.isString(value.name) ? value.name : value.name.value; + const args: string[] = value.args ? value.args.map(value => Types.isString(value) ? value : value.value) : []; + const result: ProcessExecutionDTO = { process: process, args: args }; @@ -155,7 +155,7 @@ namespace ProcessExecutionDTO { return result; } export function to(value: ProcessExecutionDTO): CommandConfiguration { - let result: CommandConfiguration = { + const result: CommandConfiguration = { runtime: RuntimeType.Process, name: value.process, args: value.args, @@ -171,7 +171,7 @@ namespace ShellExecutionOptionsDTO { if (value === undefined || value === null) { return undefined; } - let result: ShellExecutionOptionsDTO = { + const result: ShellExecutionOptionsDTO = { cwd: value.cwd || CommandOptions.defaults.cwd, env: value.env }; @@ -186,7 +186,7 @@ namespace ShellExecutionOptionsDTO { if (value === undefined || value === null) { return undefined; } - let result: CommandOptions = { + const result: CommandOptions = { cwd: value.cwd, env: value.env }; @@ -207,11 +207,11 @@ namespace ShellExecutionOptionsDTO { namespace ShellExecutionDTO { export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO { - let candidate = value as ShellExecutionDTO; + const candidate = value as ShellExecutionDTO; return candidate && (!!candidate.commandLine || !!candidate.command); } export function from(value: CommandConfiguration): ShellExecutionDTO { - let result: ShellExecutionDTO = {}; + const result: ShellExecutionDTO = {}; if (value.name && Types.isString(value.name) && (value.args === undefined || value.args === null || value.args.length === 0)) { result.commandLine = value.name; } else { @@ -224,7 +224,7 @@ namespace ShellExecutionDTO { return result; } export function to(value: ShellExecutionDTO): CommandConfiguration { - let result: CommandConfiguration = { + const result: CommandConfiguration = { runtime: RuntimeType.Shell, name: value.commandLine ? value.commandLine : value.command, args: value.args, @@ -239,7 +239,7 @@ namespace ShellExecutionDTO { namespace TaskSourceDTO { export function from(value: TaskSource): TaskSourceDTO { - let result: TaskSourceDTO = { + const result: TaskSourceDTO = { label: value.label }; if (value.kind === TaskSourceKind.Extension) { @@ -285,7 +285,7 @@ namespace TaskSourceDTO { namespace TaskHandleDTO { export function is(value: any): value is TaskHandleDTO { - let candidate: TaskHandleDTO = value; + const candidate: TaskHandleDTO = value; return candidate && Types.isString(candidate.id) && !!candidate.workspaceFolder; } } @@ -295,7 +295,7 @@ namespace TaskDTO { if (task === undefined || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) { return undefined; } - let result: TaskDTO = { + const result: TaskDTO = { _id: task._id, name: task.configurationProperties.name, definition: TaskDefinitionDTO.from(task.getDefinition()), @@ -344,12 +344,12 @@ namespace TaskDTO { return undefined; } command.presentation = TaskPresentationOptionsDTO.to(task.presentationOptions); - let source = TaskSourceDTO.to(task.source, workspace); + const source = TaskSourceDTO.to(task.source, workspace); - let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); - let definition = TaskDefinitionDTO.to(task.definition, executeOnly); - let id = `${task.source.extensionId}.${definition._key}`; - let result: ContributedTask = new ContributedTask( + const label = nls.localize('task.label', '{0}: {1}', source.label, task.name); + const definition = TaskDefinitionDTO.to(task.definition, executeOnly); + const id = `${task.source.extensionId}.${definition._key}`; + const result: ContributedTask = new ContributedTask( id, // uuidMap.getUUID(identifier) source, label, @@ -416,12 +416,12 @@ export class MainThreadTask implements MainThreadTaskShape { } public $registerTaskProvider(handle: number): Promise { - let provider: ITaskProvider = { + const provider: ITaskProvider = { provideTasks: (validTypes: IStringDictionary) => { return Promise.resolve(this._proxy.$provideTasks(handle, validTypes)).then((value) => { - let tasks: Task[] = []; + const tasks: Task[] = []; for (let dto of value.tasks) { - let task = TaskDTO.to(dto, this._workspaceContextServer, true); + const task = TaskDTO.to(dto, this._workspaceContextServer, true); if (task) { tasks.push(task); } else { @@ -435,7 +435,7 @@ export class MainThreadTask implements MainThreadTaskShape { }); } }; - let disposable = this._taskService.registerTaskProvider(provider); + const disposable = this._taskService.registerTaskProvider(provider); this._providers.set(handle, { disposable, provider }); return Promise.resolve(undefined); } @@ -448,9 +448,9 @@ export class MainThreadTask implements MainThreadTaskShape { public $fetchTasks(filter?: TaskFilterDTO): Promise { return this._taskService.tasks(TaskFilterDTO.to(filter)).then((tasks) => { - let result: TaskDTO[] = []; + const result: TaskDTO[] = []; for (let task of tasks) { - let item = TaskDTO.from(task); + const item = TaskDTO.from(task); if (item) { result.push(item); } @@ -462,12 +462,12 @@ export class MainThreadTask implements MainThreadTaskShape { public $executeTask(value: TaskHandleDTO | TaskDTO): Promise { return new Promise((resolve, reject) => { if (TaskHandleDTO.is(value)) { - let workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder)); + const workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder)); this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task) => { this._taskService.run(task).then(undefined, reason => { // eat the error, it has already been surfaced to the user and we don't care about it here }); - let result: TaskExecutionDTO = { + const result: TaskExecutionDTO = { id: value.id, task: TaskDTO.from(task) }; @@ -476,11 +476,11 @@ export class MainThreadTask implements MainThreadTaskShape { reject(new Error('Task not found')); }); } else { - let task = TaskDTO.to(value, this._workspaceContextServer, true); + const task = TaskDTO.to(value, this._workspaceContextServer, true); this._taskService.run(task).then(undefined, reason => { // eat the error, it has already been surfaced to the user and we don't care about it here }); - let result: TaskExecutionDTO = { + const result: TaskExecutionDTO = { id: task._id, task: TaskDTO.from(task) }; @@ -529,7 +529,7 @@ export class MainThreadTask implements MainThreadTaskShape { }, context: this._extHostContext, resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet): Promise => { - let vars: string[] = []; + const vars: string[] = []; toResolve.variables.forEach(item => vars.push(item)); return Promise.resolve(this._proxy.$resolveVariables(workspaceFolder.uri, { process: toResolve.process, variables: vars })).then(values => { const partiallyResolvedVars = new Array(); @@ -538,7 +538,7 @@ export class MainThreadTask implements MainThreadTaskShape { }); return new Promise((resolve, reject) => { this._configurationResolverService.resolveWithInteraction(workspaceFolder, partiallyResolvedVars, 'tasks').then(resolvedVars => { - let result: ResolvedVariables = { + const result: ResolvedVariables = { process: undefined, variables: new Map() }; diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index c3edba1ed2a..4d2e7c01c30 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -92,7 +92,7 @@ export function createApiFactory( extHostStorage: ExtHostStorage ): IExtensionApiFactory { - let schemeTransformer: ISchemeTransformer | null = null; + const schemeTransformer: ISchemeTransformer | null = null; // Addressable instances rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService); @@ -188,7 +188,7 @@ export function createApiFactory( }, registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable { return extHostCommands.registerCommand(true, id, (...args: any[]): any => { - let activeTextEditor = extHostEditors.getActiveTextEditor(); + const activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); return undefined; @@ -209,7 +209,7 @@ export function createApiFactory( }, registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => { return extHostCommands.registerCommand(true, id, async (...args: any[]): Promise => { - let activeTextEditor = extHostEditors.getActiveTextEditor(); + const activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); return undefined; @@ -566,7 +566,7 @@ export function createApiFactory( openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) { let uriPromise: Thenable; - let options = uriOrFileNameOrOptions as { language?: string; content?: string; }; + const options = uriOrFileNameOrOptions as { language?: string; content?: string; }; if (typeof uriOrFileNameOrOptions === 'string') { uriPromise = Promise.resolve(URI.file(uriOrFileNameOrOptions)); } else if (uriOrFileNameOrOptions instanceof URI) { diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index 8a54f2e10d4..ffd3502e0b7 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -263,7 +263,7 @@ export class ExtHostApiCommands { // --- command impl private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void { - let disposable = this._commands.registerCommand(false, id, handler, this, description); + const disposable = this._commands.registerCommand(false, id, handler, this, description); this._disposables.push(disposable); } @@ -408,7 +408,7 @@ export class ExtHostApiCommands { } private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise { - let pos = positions.map(typeConverters.Position.from); + const pos = positions.map(typeConverters.Position.from); const args = { resource, position: pos[0], @@ -443,7 +443,7 @@ export class ExtHostApiCommands { } class MergedInfo extends types.SymbolInformation implements vscode.DocumentSymbol { static to(symbol: modes.DocumentSymbol): MergedInfo { - let res = new MergedInfo( + const res = new MergedInfo( symbol.name, typeConverters.SymbolKind.to(symbol.kind), symbol.containerName, diff --git a/src/vs/workbench/api/node/extHostCommands.ts b/src/vs/workbench/api/node/extHostCommands.ts index acf75cefcfb..1a6b4162422 100644 --- a/src/vs/workbench/api/node/extHostCommands.ts +++ b/src/vs/workbench/api/node/extHostCommands.ts @@ -154,7 +154,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { } try { - let result = callback.apply(thisArg, args); + const result = callback.apply(thisArg, args); return Promise.resolve(result); } catch (err) { this._logService.error(err, id); diff --git a/src/vs/workbench/api/node/extHostComments.ts b/src/vs/workbench/api/node/extHostComments.ts index a5dfa6d017c..a1f3156614a 100644 --- a/src/vs/workbench/api/node/extHostComments.ts +++ b/src/vs/workbench/api/node/extHostComments.ts @@ -344,7 +344,7 @@ export class ExtHostCommentThread implements vscode.CommentThread { } getComment(commentId: string): vscode.Comment | undefined { - let comments = this._comments.filter(comment => comment.commentId === commentId); + const comments = this._comments.filter(comment => comment.commentId === commentId); if (comments && comments.length) { return comments[0]; @@ -480,7 +480,7 @@ class ExtHostCommentControl implements vscode.CommentControl { } $onActiveCommentWidgetChange(commentThread: modes.CommentThread2, comment: modes.Comment | undefined, input: string) { - let extHostCommentThread = this._threads.get(commentThread.commentThreadHandle); + const extHostCommentThread = this._threads.get(commentThread.commentThreadHandle); const extHostCommentWidget = new ExtHostCommentWidget( this._proxy, diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index c593cb4bf65..880a550dab4 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -255,7 +255,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { console.error('DebugConfigurationProvider.debugAdapterExecutable is deprecated and will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.'); } - let handle = this._configProviderHandleCounter++; + const handle = this._configProviderHandleCounter++; this._configProviders.push({ type, handle, provider }); this._debugServiceProxy.$registerDebugConfigurationProvider(type, @@ -286,7 +286,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { throw new Error(`a DebugAdapterDescriptorFactory can only be registered once per a type.`); } - let handle = this._adapterFactoryHandleCounter++; + const handle = this._adapterFactoryHandleCounter++; this._adapterFactories.push({ type, handle, factory }); this._debugServiceProxy.$registerDebugAdapterDescriptorFactory(type, handle); @@ -303,7 +303,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { return new Disposable(() => { }); } - let handle = this._trackerFactoryHandleCounter++; + const handle = this._trackerFactoryHandleCounter++; this._trackerFactories.push({ type, handle, factory }); this._debugServiceProxy.$registerDebugAdapterTrackerFactory(type, handle); @@ -494,9 +494,9 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { public $acceptBreakpointsDelta(delta: IBreakpointsDeltaDto): void { - let a: vscode.Breakpoint[] = []; - let r: vscode.Breakpoint[] = []; - let c: vscode.Breakpoint[] = []; + const a: vscode.Breakpoint[] = []; + const r: vscode.Breakpoint[] = []; + const c: vscode.Breakpoint[] = []; if (delta.added) { for (const bpd of delta.added) { @@ -528,7 +528,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { if (delta.changed) { for (const bpd of delta.changed) { - let bp = this._breakpoints.get(bpd.id); + const bp = this._breakpoints.get(bpd.id); if (bp) { if (bp instanceof FunctionBreakpoint && bpd.type === 'function') { const fbp = bp; @@ -554,7 +554,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise { - let provider = this.getConfigProviderByHandle(configProviderHandle); + const provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); } @@ -566,7 +566,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise { - let provider = this.getConfigProviderByHandle(configProviderHandle); + const provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); } @@ -579,7 +579,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { // TODO@AW legacy public async $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise { - let provider = this.getConfigProviderByHandle(configProviderHandle); + const provider = this.getConfigProviderByHandle(configProviderHandle); if (!provider) { return Promise.reject(new Error('no handler found')); } @@ -591,7 +591,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { } public async $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Promise { - let adapterProvider = this.getAdapterProviderByHandle(adapterProviderHandle); + const adapterProvider = this.getAdapterProviderByHandle(adapterProviderHandle); if (!adapterProvider) { return Promise.reject(new Error('no handler found')); } diff --git a/src/vs/workbench/api/node/extHostDiagnostics.ts b/src/vs/workbench/api/node/extHostDiagnostics.ts index fe511a50994..8a54b7e405c 100644 --- a/src/vs/workbench/api/node/extHostDiagnostics.ts +++ b/src/vs/workbench/api/node/extHostDiagnostics.ts @@ -115,7 +115,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { const entries: [URI, IMarkerData[]][] = []; for (let uri of toSync) { let marker: IMarkerData[] = []; - let diagnostics = this._data.get(uri.toString()); + const diagnostics = this._data.get(uri.toString()); if (diagnostics) { // no more than N diagnostics per file @@ -170,14 +170,14 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { forEach(callback: (uri: URI, diagnostics: vscode.Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void { this._checkDisposed(); this._data.forEach((value, key) => { - let uri = URI.parse(key); + const uri = URI.parse(key); callback.apply(thisArg, [uri, this.get(uri), this]); }); } get(uri: URI): vscode.Diagnostic[] { this._checkDisposed(); - let result = this._data.get(uri.toString()); + const result = this._data.get(uri.toString()); if (Array.isArray(result)) { return Object.freeze(result.slice(0)); } @@ -224,8 +224,8 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape { } static _mapper(last: (vscode.Uri | string)[]): { uris: vscode.Uri[] } { - let uris: vscode.Uri[] = []; - let map = new Set(); + const uris: vscode.Uri[] = []; + const map = new Set(); for (const uri of last) { if (typeof uri === 'string') { if (!map.has(uri)) { @@ -285,8 +285,8 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape { if (resource) { return this._getDiagnostics(resource); } else { - let index = new Map(); - let res: [vscode.Uri, vscode.Diagnostic[]][] = []; + const index = new Map(); + const res: [vscode.Uri, vscode.Diagnostic[]][] = []; this._collections.forEach(collection => { collection.forEach((uri, diagnostics) => { let idx = index.get(uri.toString()); diff --git a/src/vs/workbench/api/node/extHostDocumentData.ts b/src/vs/workbench/api/node/extHostDocumentData.ts index c05dbb6855d..e875c30af2b 100644 --- a/src/vs/workbench/api/node/extHostDocumentData.ts +++ b/src/vs/workbench/api/node/extHostDocumentData.ts @@ -105,7 +105,7 @@ export class ExtHostDocumentData extends MirrorTextModel { } private _getTextInRange(_range: vscode.Range): string { - let range = this._validateRange(_range); + const range = this._validateRange(_range); if (range.isEmpty) { return ''; @@ -115,7 +115,7 @@ export class ExtHostDocumentData extends MirrorTextModel { return this._lines[range.start.line].substring(range.start.character, range.end.character); } - let lineEnding = this._eol, + const lineEnding = this._eol, startLineIndex = range.start.line, endLineIndex = range.end.line, resultLines: string[] = []; @@ -178,9 +178,9 @@ export class ExtHostDocumentData extends MirrorTextModel { offset = Math.max(0, offset); this._ensureLineStarts(); - let out = this._lineStarts!.getIndexOf(offset); + const out = this._lineStarts!.getIndexOf(offset); - let lineLength = this._lines[out.index].length; + const lineLength = this._lines[out.index].length; // Ensure we return a valid position return new Position(out.index, Math.min(out.remainder, lineLength)); @@ -193,8 +193,8 @@ export class ExtHostDocumentData extends MirrorTextModel { throw new Error('Invalid argument'); } - let start = this._validatePosition(range.start); - let end = this._validatePosition(range.end); + const start = this._validatePosition(range.start); + const end = this._validatePosition(range.end); if (start === range.start && end === range.end) { return range; @@ -221,7 +221,7 @@ export class ExtHostDocumentData extends MirrorTextModel { hasChanged = true; } else { - let maxCharacter = this._lines[line].length; + const maxCharacter = this._lines[line].length; if (character < 0) { character = 0; hasChanged = true; @@ -239,7 +239,7 @@ export class ExtHostDocumentData extends MirrorTextModel { } private _getWordRangeAtPosition(_position: vscode.Position, regexp?: RegExp): vscode.Range | undefined { - let position = this._validatePosition(_position); + const position = this._validatePosition(_position); if (!regexp) { // use default when custom-regexp isn't provided @@ -251,7 +251,7 @@ export class ExtHostDocumentData extends MirrorTextModel { regexp = getWordDefinitionFor(this._languageId); } - let wordAtText = getWordAtText( + const wordAtText = getWordAtText( position.character + 1, ensureValidWordDefinition(regexp), this._lines[position.line], diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index d8a99d2aaee..2225d4dbc06 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -53,7 +53,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic const entries = this._callbacks.toArray(); let didTimeout = false; - let didTimeoutHandle = setTimeout(() => didTimeout = true, this._thresholds.timeout); + const didTimeoutHandle = setTimeout(() => didTimeout = true, this._thresholds.timeout); const promise = sequence(entries.map(listener => { return () => { diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index 40ae4c8a371..2383a6eb83a 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -77,7 +77,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { public ensureDocumentData(uri: URI): Promise { - let cached = this._documentsAndEditors.getDocument(uri); + const cached = this._documentsAndEditors.getDocument(uri); if (cached) { return Promise.resolve(cached); } diff --git a/src/vs/workbench/api/node/extHostExtensionActivator.ts b/src/vs/workbench/api/node/extHostExtensionActivator.ts index b6f50845288..a248e0e9f69 100644 --- a/src/vs/workbench/api/node/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/node/extHostExtensionActivator.ts @@ -238,14 +238,14 @@ export class ExtensionsActivator { if (this._alreadyActivatedEvents[activationEvent]) { return NO_OP_VOID_PROMISE; } - let activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent); + const activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent); return this._activateExtensions(activateExtensions.map(e => e.identifier), reason).then(() => { this._alreadyActivatedEvents[activationEvent] = true; }); } public activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { - let desc = this._registry.getExtensionDescription(extensionId); + const desc = this._registry.getExtensionDescription(extensionId); if (!desc) { throw new Error('Extension `' + extensionId + '` is not known'); } @@ -264,7 +264,7 @@ export class ExtensionsActivator { } const currentExtension = this._registry.getExtensionDescription(currentExtensionId)!; - let depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies); + const depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies); let currentExtensionGetsGreenLight = true; for (let j = 0, lenJ = depIds.length; j < lenJ; j++) { @@ -330,7 +330,7 @@ export class ExtensionsActivator { return Promise.resolve(undefined); } - let greenMap: { [id: string]: ExtensionIdentifier; } = Object.create(null), + const greenMap: { [id: string]: ExtensionIdentifier; } = Object.create(null), red: ExtensionIdentifier[] = []; for (let i = 0, len = extensionIds.length; i < len; i++) { @@ -345,7 +345,7 @@ export class ExtensionsActivator { } } - let green = Object.keys(greenMap).map(id => greenMap[id]); + const green = Object.keys(greenMap).map(id => greenMap[id]); // console.log('greenExtensions: ', green.map(p => p.id)); // console.log('redExtensions: ', red.map(p => p.id)); diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 9eae6df41cf..8114ceb234a 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -225,7 +225,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise => { if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) { - let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); + const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent); return new HostExtension(); } @@ -345,7 +345,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { return result; } - let extension = this._activator.getActivatedExtension(extensionId); + const extension = this._activator.getActivatedExtension(extensionId); if (!extension) { return result; } @@ -382,7 +382,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier); return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => { const activationTimes = activatedExtension.activationTimes; - let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); + const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent); this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes); return activatedExtension; @@ -394,7 +394,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) { - let event = getTelemetryActivationEvent(extensionDescription, reason); + const event = getTelemetryActivationEvent(extensionDescription, reason); /* __GDPR__ "extensionActivationTimes" : { "${include}": [ @@ -412,7 +412,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise { - let event = getTelemetryActivationEvent(extensionDescription, reason); + const event = getTelemetryActivationEvent(extensionDescription, reason); /* __GDPR__ "activatePlugin" : { "${include}": [ @@ -439,8 +439,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise { - let globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage); - let workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage); + const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage); + const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage); this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`); return Promise.all([ @@ -763,7 +763,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } public async $test_down(size: number): Promise { - let b = Buffer.alloc(size, Math.random() % 256); + const b = Buffer.alloc(size, Math.random() % 256); return b; } @@ -799,7 +799,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription "reason": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - let event = { + const event = { id: extensionDescription.identifier.value, name: extensionDescription.name, extensionVersion: extensionDescription.version, diff --git a/src/vs/workbench/api/node/extHostFileSystem.ts b/src/vs/workbench/api/node/extHostFileSystem.ts index 29cf43d41a3..8a83afc3ca4 100644 --- a/src/vs/workbench/api/node/extHostFileSystem.ts +++ b/src/vs/workbench/api/node/extHostFileSystem.ts @@ -28,7 +28,7 @@ class FsLinkProvider { } delete(scheme: string): void { - let idx = this._schemes.indexOf(scheme); + const idx = this._schemes.indexOf(scheme); if (idx >= 0) { this._schemes.splice(idx, 1); this._stateMachine = undefined; @@ -94,7 +94,7 @@ class FsLinkProvider { }, this._stateMachine); for (const link of links) { - let docLink = typeConverter.DocumentLink.to(link); + const docLink = typeConverter.DocumentLink.to(link); if (docLink.target) { result.push(docLink); } @@ -172,7 +172,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { this._proxy.$registerFileSystemProvider(handle, scheme, capabilites); const subscription = provider.onDidChangeFile(event => { - let mapped: IFileChangeDto[] = []; + const mapped: IFileChangeDto[] = []; for (const e of event) { let { uri: resource, type } = e; if (resource.scheme !== scheme) { @@ -260,12 +260,12 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { } $watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void { - let subscription = this.getProvider(handle).watch(URI.revive(resource), opts); + const subscription = this.getProvider(handle).watch(URI.revive(resource), opts); this._watches.set(session, subscription); } $unwatch(_handle: number, session: number): void { - let subscription = this._watches.get(session); + const subscription = this._watches.get(session); if (subscription) { subscription.dispose(); this._watches.delete(session); diff --git a/src/vs/workbench/api/node/extHostFileSystemEventService.ts b/src/vs/workbench/api/node/extHostFileSystemEventService.ts index f7f682b6281..6d709b3a107 100644 --- a/src/vs/workbench/api/node/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/node/extHostFileSystemEventService.ts @@ -49,10 +49,10 @@ class FileSystemWatcher implements vscode.FileSystemWatcher { const parsedPattern = parse(globPattern); - let subscription = dispatcher(events => { + const subscription = dispatcher(events => { if (!ignoreCreateEvents) { for (let created of events.created) { - let uri = URI.revive(created); + const uri = URI.revive(created); if (parsedPattern(uri.fsPath)) { this._onDidCreate.fire(uri); } @@ -60,7 +60,7 @@ class FileSystemWatcher implements vscode.FileSystemWatcher { } if (!ignoreChangeEvents) { for (let changed of events.changed) { - let uri = URI.revive(changed); + const uri = URI.revive(changed); if (parsedPattern(uri.fsPath)) { this._onDidChange.fire(uri); } @@ -68,7 +68,7 @@ class FileSystemWatcher implements vscode.FileSystemWatcher { } if (!ignoreDeleteEvents) { for (let deleted of events.deleted) { - let uri = URI.revive(deleted); + const uri = URI.revive(deleted); if (parsedPattern(uri.fsPath)) { this._onDidDelete.fire(uri); } @@ -169,7 +169,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ } // flatten all WorkspaceEdits collected via waitUntil-call // and apply them in one go. - let allEdits = new Array>(); + const allEdits = new Array>(); for (let edit of edits) { if (edit) { // sparse array let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors); diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 54f34709fa2..d1cb405a281 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -65,10 +65,10 @@ class DocumentSymbolAdapter { } return res; }); - let res: modes.DocumentSymbol[] = []; - let parentStack: modes.DocumentSymbol[] = []; + const res: modes.DocumentSymbol[] = []; + const parentStack: modes.DocumentSymbol[] = []; for (const info of infos) { - let element = { + const element = { name: info.name || '!!MISSING: name!!', kind: typeConvert.SymbolKind.from(info.kind), containerName: info.containerName, @@ -83,7 +83,7 @@ class DocumentSymbolAdapter { res.push(element); break; } - let parent = parentStack[parentStack.length - 1]; + const parent = parentStack[parentStack.length - 1]; if (EditorRange.containsRange(parent.range, element.range) && !EditorRange.equalsRange(parent.range, element.range)) { parent.children.push(element); parentStack.push(element); @@ -111,7 +111,7 @@ class CodeLensAdapter { const doc = this._documents.getDocument(resource); return asPromise(() => this._provider.provideCodeLenses(doc, token)).then(lenses => { - let result: CodeLensDto[] = []; + const result: CodeLensDto[] = []; if (isNonEmptyArray(lenses)) { for (const lens of lenses) { const id = this._heapService.keep(lens); @@ -206,7 +206,7 @@ class DefinitionAdapter { provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideDefinition(doc, pos, token)).then(convertToLocationLinks); } } @@ -220,7 +220,7 @@ class DeclarationAdapter { provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideDeclaration(doc, pos, token)).then(convertToLocationLinks); } } @@ -234,7 +234,7 @@ class ImplementationAdapter { provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideImplementation(doc, pos, token)).then(convertToLocationLinks); } } @@ -263,7 +263,7 @@ class HoverAdapter { public provideHover(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideHover(doc, pos, token)).then(value => { if (!value || isFalsyOrEmpty(value.contents)) { @@ -291,7 +291,7 @@ class DocumentHighlightAdapter { provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => { if (Array.isArray(value)) { @@ -311,7 +311,7 @@ class ReferenceAdapter { provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideReferences(doc, pos, context, token)).then(value => { if (Array.isArray(value)) { @@ -546,7 +546,7 @@ class RenameAdapter { provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise { const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => { if (!value) { @@ -554,7 +554,7 @@ class RenameAdapter { } return typeConvert.WorkspaceEdit.from(value); }, err => { - let rejectReason = RenameAdapter._asMessage(err); + const rejectReason = RenameAdapter._asMessage(err); if (rejectReason) { return { rejectReason, edits: undefined! }; } else { @@ -570,7 +570,7 @@ class RenameAdapter { } const doc = this._documents.getDocument(resource); - let pos = typeConvert.Position.to(position); + const pos = typeConvert.Position.to(position); return asPromise(() => this._provider.prepareRename!(doc, pos, token)).then(rangeOrLocation => { @@ -594,7 +594,7 @@ class RenameAdapter { } return { range: typeConvert.Range.from(range), text }; }, err => { - let rejectReason = RenameAdapter._asMessage(err); + const rejectReason = RenameAdapter._asMessage(err); if (rejectReason) { return { rejectReason, range: undefined!, text: undefined! }; } else { @@ -832,8 +832,8 @@ class LinkProviderAdapter { } const result: LinkDto[] = []; for (const link of links) { - let data = typeConvert.DocumentLink.from(link); - let id = this._heapService.keep(link); + const data = typeConvert.DocumentLink.from(link); + const id = this._heapService.keep(link); result.push(ObjectIdentifier.mixin(data, id)); } return result; @@ -936,7 +936,7 @@ class SelectionRangeAdapter { return []; } - let allResults: modes.SelectionRange[][] = []; + const allResults: modes.SelectionRange[][] = []; for (let i = 0; i < positions.length; i++) { const oneResult: modes.SelectionRange[] = []; allResults.push(oneResult); @@ -1065,7 +1065,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { t1 = Date.now(); this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${(ctor as any).name}'`); } - let p = callback(data.adapter, data.extension); + const p = callback(data.adapter, data.extension); const extension = data.extension; if (extension) { Promise.resolve(p).then( diff --git a/src/vs/workbench/api/node/extHostMessageService.ts b/src/vs/workbench/api/node/extHostMessageService.ts index ea85d1d6d99..635f076610d 100644 --- a/src/vs/workbench/api/node/extHostMessageService.ts +++ b/src/vs/workbench/api/node/extHostMessageService.ts @@ -24,7 +24,7 @@ export class ExtHostMessageService { showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Promise; showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Promise { - let options: MainThreadMessageOptions = { extension }; + const options: MainThreadMessageOptions = { extension }; let items: (string | vscode.MessageItem)[]; if (typeof optionsOrFirstItem === 'string' || isMessageItem(optionsOrFirstItem)) { @@ -37,7 +37,7 @@ export class ExtHostMessageService { const commands: { title: string; isCloseAffordance: boolean; handle: number; }[] = []; for (let handle = 0; handle < items.length; handle++) { - let command = items[handle]; + const command = items[handle]; if (typeof command === 'string') { commands.push({ title: command, handle, isCloseAffordance: false }); } else if (typeof command === 'object') { diff --git a/src/vs/workbench/api/node/extHostQuickOpen.ts b/src/vs/workbench/api/node/extHostQuickOpen.ts index 1a8fbce1a76..9aedb8e14e6 100644 --- a/src/vs/workbench/api/node/extHostQuickOpen.ts +++ b/src/vs/workbench/api/node/extHostQuickOpen.ts @@ -68,10 +68,10 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { return itemsPromise.then(items => { - let pickItems: TransferQuickPickItems[] = []; + const pickItems: TransferQuickPickItems[] = []; for (let handle = 0; handle < items.length; handle++) { - let item = items[handle]; + const item = items[handle]; let label: string; let description: string | undefined; let detail: string | undefined; diff --git a/src/vs/workbench/api/node/extHostSearch.fileIndex.ts b/src/vs/workbench/api/node/extHostSearch.fileIndex.ts index 57ccbf500e8..9ca147e4cfe 100644 --- a/src/vs/workbench/api/node/extHostSearch.fileIndex.ts +++ b/src/vs/workbench/api/node/extHostSearch.fileIndex.ts @@ -116,7 +116,7 @@ export class FileIndexSearchEngine { } private searchInFolder(fq: IFolderQuery, onResult: (match: IInternalFileMatch) => void): Promise { - let cancellation = new CancellationTokenSource(); + const cancellation = new CancellationTokenSource(); return new Promise((resolve, reject) => { const options = this.getSearchOptionsForFolder(fq); const tree = this.initDirectoryTree(); @@ -511,10 +511,10 @@ export class FileIndexSearchManager { } // Pattern match on results - let results: IInternalFileMatch[] = []; + const results: IInternalFileMatch[] = []; const normalizedSearchValueLowercase = strings.stripWildcards(searchValue).toLowerCase(); for (let i = 0; i < complete.results.length; i++) { - let entry = complete.results[i]; + const entry = complete.results[i]; // Check if this entry is a match for the search value if (!strings.fuzzyContains(entry.relativePath!, normalizedSearchValueLowercase)) { diff --git a/src/vs/workbench/api/node/extHostStatusBar.ts b/src/vs/workbench/api/node/extHostStatusBar.ts index e5ff768408b..cd6c2066146 100644 --- a/src/vs/workbench/api/node/extHostStatusBar.ts +++ b/src/vs/workbench/api/node/extHostStatusBar.ts @@ -139,7 +139,7 @@ class StatusBarMessage { this._update(); return new Disposable(() => { - let idx = this._messages.indexOf(data); + const idx = this._messages.indexOf(data); if (idx >= 0) { this._messages.splice(idx, 1); this._update(); @@ -173,7 +173,7 @@ export class ExtHostStatusBar { setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): Disposable { - let d = this._statusMessage.setMessage(text); + const d = this._statusMessage.setMessage(text); let handle: any; if (typeof timeoutOrThenable === 'number') { diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index eeed4f06b6e..8d2fc278b45 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -75,14 +75,14 @@ namespace ProcessExecutionOptionsDTO { namespace ProcessExecutionDTO { export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO { - let candidate = value as ProcessExecutionDTO; + const candidate = value as ProcessExecutionDTO; return candidate && !!candidate.process; } export function from(value: vscode.ProcessExecution): ProcessExecutionDTO { if (value === undefined || value === null) { return undefined; } - let result: ProcessExecutionDTO = { + const result: ProcessExecutionDTO = { process: value.process, args: value.args }; @@ -116,14 +116,14 @@ namespace ShellExecutionOptionsDTO { namespace ShellExecutionDTO { export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO { - let candidate = value as ShellExecutionDTO; + const candidate = value as ShellExecutionDTO; return candidate && (!!candidate.commandLine || !!candidate.command); } export function from(value: vscode.ShellExecution): ShellExecutionDTO { if (value === undefined || value === null) { return undefined; } - let result: ShellExecutionDTO = { + const result: ShellExecutionDTO = { }; if (value.commandLine !== undefined) { result.commandLine = value.commandLine; @@ -167,9 +167,9 @@ namespace TaskDTO { if (tasks === undefined || tasks === null) { return []; } - let result: TaskDTO[] = []; + const result: TaskDTO[] = []; for (let task of tasks) { - let converted = from(task, extension); + const converted = from(task, extension); if (converted) { result.push(converted); } @@ -187,7 +187,7 @@ namespace TaskDTO { } else if (value.execution instanceof types.ShellExecution) { execution = ShellExecutionDTO.from(value.execution); } - let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition); + const definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition); let scope: number | UriComponents; if (value.scope) { if (typeof value.scope === 'number') { @@ -202,8 +202,8 @@ namespace TaskDTO { if (!definition || !scope) { return undefined; } - let group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined; - let result: TaskDTO = { + const group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined; + const result: TaskDTO = { _id: (value as types.Task)._id, definition, name: value.name, @@ -232,7 +232,7 @@ namespace TaskDTO { } else if (ShellExecutionDTO.is(value.execution)) { execution = ShellExecutionDTO.to(value.execution); } - let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition); + const definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition); let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder | undefined; if (value.source) { if (value.source.scope !== undefined) { @@ -248,7 +248,7 @@ namespace TaskDTO { if (!definition || !scope) { return undefined; } - let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers); + const result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers); if (value.isBackground !== undefined) { result.isBackground = value.isBackground; } @@ -345,7 +345,7 @@ export class ExtHostTask implements ExtHostTaskShape { if (!provider) { return new types.Disposable(() => { }); } - let handle = this.nextHandle(); + const handle = this.nextHandle(); this._handlers.set(handle, { provider, extension }); this._proxy.$registerTaskProvider(handle); return new types.Disposable(() => { @@ -360,9 +360,9 @@ export class ExtHostTask implements ExtHostTaskShape { public fetchTasks(filter?: vscode.TaskFilter): Promise { return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then(async (values) => { - let result: vscode.Task[] = []; + const result: vscode.Task[] = []; for (let value of values) { - let task = await TaskDTO.to(value, this._workspaceProvider); + const task = await TaskDTO.to(value, this._workspaceProvider); if (task) { result.push(task); } @@ -372,12 +372,12 @@ export class ExtHostTask implements ExtHostTaskShape { } public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise { - let tTask = (task as types.Task); + const tTask = (task as types.Task); // We have a preserved ID. So the task didn't change. if (tTask._id !== undefined) { return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task)); } else { - let dto = TaskDTO.from(task, extension); + const dto = TaskDTO.from(task, extension); if (dto === undefined) { return Promise.reject(new Error('Task is not valid')); } @@ -386,7 +386,7 @@ export class ExtHostTask implements ExtHostTaskShape { } public get taskExecutions(): vscode.TaskExecution[] { - let result: vscode.TaskExecution[] = []; + const result: vscode.TaskExecution[] = []; this._taskExecutions.forEach(value => result.push(value)); return result; } @@ -449,12 +449,12 @@ export class ExtHostTask implements ExtHostTaskShape { } public $provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable { - let handler = this._handlers.get(handle); + const handler = this._handlers.get(handle); if (!handler) { return Promise.reject(new Error('no handler found')); } return asPromise(() => handler.provider.provideTasks(CancellationToken.None)).then(value => { - let sanitized: vscode.Task[] = []; + const sanitized: vscode.Task[] = []; for (let task of value) { if (task.definition && validTypes[task.definition.type] === true) { sanitized.push(task); @@ -472,15 +472,15 @@ export class ExtHostTask implements ExtHostTaskShape { public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> { const configProvider = await this._configurationService.getConfigProvider(); - let uri: URI = URI.revive(uriComponents); - let result = { + const uri: URI = URI.revive(uriComponents); + const result = { process: undefined as string, variables: Object.create(null) }; - let workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(uri); + const workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(uri); const workspaceFolders = await this._workspaceProvider.getWorkspaceFolders2(); - let resolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider); - let ws: IWorkspaceFolder = { + const resolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider); + const ws: IWorkspaceFolder = { uri: workspaceFolder.uri, name: workspaceFolder.name, index: workspaceFolder.index, diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index ae9ea2f67cf..d3080e367b6 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -106,7 +106,7 @@ export class TextEditorEdit { } private _pushEdit(range: Range, text: string | null, forceMoveMarkers: boolean): void { - let validRange = this._document.validateRange(range); + const validRange = this._document.validateRange(range); this._collectedEdits.push({ range: validRange, text: text, @@ -170,11 +170,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { return 'auto'; } if (typeof value === 'number') { - let r = Math.floor(value); + const r = Math.floor(value); return (r > 0 ? r : null); } if (typeof value === 'string') { - let r = parseInt(value, 10); + const r = parseInt(value, 10); if (isNaN(r)) { return null; } @@ -184,7 +184,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { } public set tabSize(value: number | string) { - let tabSize = this._validateTabSize(value); + const tabSize = this._validateTabSize(value); if (tabSize === null) { // ignore invalid call return; @@ -211,11 +211,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { return 'tabSize'; } if (typeof value === 'number') { - let r = Math.floor(value); + const r = Math.floor(value); return (r > 0 ? r : null); } if (typeof value === 'string') { - let r = parseInt(value, 10); + const r = parseInt(value, 10); if (isNaN(r)) { return null; } @@ -225,7 +225,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { } public set indentSize(value: number | string) { - let indentSize = this._validateIndentSize(value); + const indentSize = this._validateIndentSize(value); if (indentSize === null) { // ignore invalid call return; @@ -255,7 +255,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { } public set insertSpaces(value: boolean | string) { - let insertSpaces = this._validateInsertSpaces(value); + const insertSpaces = this._validateInsertSpaces(value); if (typeof insertSpaces === 'boolean') { if (this._insertSpaces === insertSpaces) { // nothing to do @@ -300,11 +300,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { } public assign(newOptions: vscode.TextEditorOptions) { - let bulkConfigurationUpdate: ITextEditorConfigurationUpdate = {}; + const bulkConfigurationUpdate: ITextEditorConfigurationUpdate = {}; let hasUpdate = false; if (typeof newOptions.tabSize !== 'undefined') { - let tabSize = this._validateTabSize(newOptions.tabSize); + const tabSize = this._validateTabSize(newOptions.tabSize); if (tabSize === 'auto') { hasUpdate = true; bulkConfigurationUpdate.tabSize = tabSize; @@ -317,7 +317,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { } // if (typeof newOptions.indentSize !== 'undefined') { - // let indentSize = this._validateIndentSize(newOptions.indentSize); + // const indentSize = this._validateIndentSize(newOptions.indentSize); // if (indentSize === 'tabSize') { // hasUpdate = true; // bulkConfigurationUpdate.indentSize = indentSize; @@ -330,7 +330,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { // } if (typeof newOptions.insertSpaces !== 'undefined') { - let insertSpaces = this._validateInsertSpaces(newOptions.insertSpaces); + const insertSpaces = this._validateInsertSpaces(newOptions.insertSpaces); if (insertSpaces === 'auto') { hasUpdate = true; bulkConfigurationUpdate.insertSpaces = insertSpaces; @@ -510,7 +510,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { TypeConverters.fromRangeOrRangeWithMessage(ranges) ); } else { - let _ranges: number[] = new Array(4 * ranges.length); + const _ranges: number[] = new Array(4 * ranges.length); for (let i = 0, len = ranges.length; i < len; i++) { const range = ranges[i]; _ranges[4 * i] = range.start.line + 1; @@ -539,7 +539,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { } private _trySetSelection(): Promise { - let selection = this._selections.map(TypeConverters.Selection.from); + const selection = this._selections.map(TypeConverters.Selection.from); return this._runOnProxy(() => this._proxy.$trySetSelections(this._id, selection)); } @@ -554,13 +554,13 @@ export class ExtHostTextEditor implements vscode.TextEditor { if (this._disposed) { return Promise.reject(new Error('TextEditor#edit not possible on closed editors')); } - let edit = new TextEditorEdit(this._documentData.document, options); + const edit = new TextEditorEdit(this._documentData.document, options); callback(edit); return this._applyEdit(edit); } private _applyEdit(editBuilder: TextEditorEdit): Promise { - let editData = editBuilder.finalize(); + const editData = editBuilder.finalize(); // return when there is nothing to do if (editData.edits.length === 0 && !editData.setEndOfLine) { @@ -568,7 +568,7 @@ export class ExtHostTextEditor implements vscode.TextEditor { } // check that the edits are not overlapping (i.e. illegal) - let editRanges = editData.edits.map(edit => edit.range); + const editRanges = editData.edits.map(edit => edit.range); // sort ascending (by end and then by start) editRanges.sort((a, b) => { diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index 5e6e2dfb5a1..a42ec9c245f 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -75,7 +75,7 @@ export class ExtHostEditors implements ExtHostEditorsShape { } return this._proxy.$tryShowTextDocument(document.uri, options).then(id => { - let editor = this._extHostDocumentsAndEditors.getEditor(id); + const editor = this._extHostDocumentsAndEditors.getEditor(id); if (editor) { return editor; } else { diff --git a/src/vs/workbench/api/node/extHostTreeViews.ts b/src/vs/workbench/api/node/extHostTreeViews.ts index f5e8ea7aba9..b135cd62d8d 100644 --- a/src/vs/workbench/api/node/extHostTreeViews.ts +++ b/src/vs/workbench/api/node/extHostTreeViews.ts @@ -366,7 +366,7 @@ class ExtHostTreeView extends Disposable { private getHandlesToRefresh(elements: T[]): TreeItemHandle[] { const elementsToUpdate = new Set(); for (const element of elements) { - let elementNode = this.nodes.get(element); + const elementNode = this.nodes.get(element); if (elementNode && !elementsToUpdate.has(elementNode.item.handle)) { // check if an ancestor of extElement is already in the elements to update list let currentNode = elementNode; @@ -384,7 +384,7 @@ class ExtHostTreeView extends Disposable { // Take only top level elements elementsToUpdate.forEach((handle) => { const element = this.elements.get(handle); - let node = this.nodes.get(element); + const node = this.nodes.get(element); if (node && (!node.parent || !elementsToUpdate.has(node.parent.item.handle))) { handlesToUpdate.push(handle); } @@ -553,7 +553,7 @@ class ExtHostTreeView extends Disposable { private clearChildren(parentElement?: T): void { if (parentElement) { - let node = this.nodes.get(parentElement); + const node = this.nodes.get(parentElement); if (node.children) { for (const child of node.children) { const childEleement = this.elements.get(child.item.handle); @@ -569,7 +569,7 @@ class ExtHostTreeView extends Disposable { } private clear(element: T): void { - let node = this.nodes.get(element); + const node = this.nodes.get(element); if (node.children) { for (const child of node.children) { const childEleement = this.elements.get(child.item.handle); diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index 54006bf3829..b87947ae0b8 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -236,7 +236,7 @@ export namespace MarkdownString { const resUris: { [href: string]: UriComponents } = Object.create(null); res.uris = resUris; - let renderer = new marked.Renderer(); + const renderer = new marked.Renderer(); renderer.image = renderer.link = (href: string): string => { try { let uri = URI.parse(href, true); @@ -267,7 +267,7 @@ export namespace MarkdownString { } data = cloneAndChange(data, value => { if (value instanceof URI) { - let key = `__uri_${Math.random().toString(16).slice(2, 8)}`; + const key = `__uri_${Math.random().toString(16).slice(2, 8)}`; bucket[key] = value; return key; } else { diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 71dc9a8b3a7..535dadfb0c8 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -66,7 +66,7 @@ export class Position { } let result = positions[0]; for (let i = 1; i < positions.length; i++) { - let p = positions[i]; + const p = positions[i]; if (p.isBefore(result!)) { result = p; } @@ -80,7 +80,7 @@ export class Position { } let result = positions[0]; for (let i = 1; i < positions.length; i++) { - let p = positions[i]; + const p = positions[i]; if (p.isAfter(result!)) { result = p; } @@ -303,8 +303,8 @@ export class Range { } intersection(other: Range): Range | undefined { - let start = Position.Max(other.start, this._start); - let end = Position.Min(other.end, this._end); + const start = Position.Max(other.start, this._start); + const end = Position.Min(other.end, this._end); if (start.isAfter(end)) { // this happens when there is no overlap: // |-----| @@ -320,8 +320,8 @@ export class Range { } else if (other.contains(this)) { return other; } - let start = Position.Min(other.start, this._start); - let end = Position.Max(other.end, this.end); + const start = Position.Min(other.start, this._start); + const end = Position.Max(other.end, this.end); return new Range(start, end); } @@ -480,7 +480,7 @@ export class TextEdit { } static setEndOfLine(eol: EndOfLine): TextEdit { - let ret = new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), ''); + const ret = new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), ''); ret.newEol = eol; return ret; } @@ -616,7 +616,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit { } get(uri: URI): TextEdit[] { - let res: TextEdit[] = []; + const res: TextEdit[] = []; for (let candidate of this._edits) { if (candidate._type === 2 && candidate.uri.toString() === uri.toString()) { res.push(candidate.edit); @@ -626,7 +626,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit { } entries(): [URI, TextEdit[]][] { - let textEdits = new Map(); + const textEdits = new Map(); for (let candidate of this._edits) { if (candidate._type === 2) { let textEdit = textEdits.get(candidate.uri.toString()); @@ -641,7 +641,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit { } _allEntries(): ([URI, TextEdit[]] | [URI?, URI?, IFileOperationOptions?])[] { - let res: ([URI, TextEdit[]] | [URI?, URI?, IFileOperationOptions?])[] = []; + const res: ([URI, TextEdit[]] | [URI?, URI?, IFileOperationOptions?])[] = []; for (let edit of this._edits) { if (edit._type === 1) { res.push([edit.from, edit.to, edit.options]); @@ -1846,7 +1846,7 @@ export class Task implements vscode.Task { } this.clear(); this._execution = value; - let type = this._definition.type; + const type = this._definition.type; if (Task.EmptyType === type || Task.ProcessType === type || Task.ShellType === type) { this.computeDefinitionBasedOnExecution(); } diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index edcbfaee62e..785ad829cba 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -459,7 +459,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac excludePattern: options.exclude ? globPatternToString(options.exclude) : undefined }; - let isCanceled = false; + const isCanceled = false; this._activeSearchCallbacks[requestId] = p => { if (isCanceled) { From 3f93ea65210fd28eb9507795738bb741cf0a1a7a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 16:48:35 -0800 Subject: [PATCH 132/172] Auto convert let -> const in base/common --- src/vs/base/common/arrays.ts | 12 +++--- src/vs/base/common/async.ts | 8 ++-- src/vs/base/common/cancellation.ts | 2 +- src/vs/base/common/color.ts | 2 +- src/vs/base/common/comparers.ts | 18 ++++---- src/vs/base/common/errors.ts | 4 +- src/vs/base/common/event.ts | 14 +++---- src/vs/base/common/extpath.ts | 6 +-- src/vs/base/common/filters.ts | 42 +++++++++---------- src/vs/base/common/glob.ts | 8 ++-- src/vs/base/common/history.ts | 2 +- src/vs/base/common/json.ts | 58 +++++++++++++------------- src/vs/base/common/jsonEdit.ts | 42 +++++++++---------- src/vs/base/common/jsonFormatter.ts | 20 ++++----- src/vs/base/common/keyCodes.ts | 10 ++--- src/vs/base/common/keybindingLabels.ts | 4 +- src/vs/base/common/keybindingParser.ts | 4 +- src/vs/base/common/linkedList.ts | 4 +- src/vs/base/common/map.ts | 48 ++++++++++----------- src/vs/base/common/objects.ts | 4 +- src/vs/base/common/parsers.ts | 4 +- src/vs/base/common/path.ts | 42 +++++++++---------- src/vs/base/common/platform.ts | 8 ++-- src/vs/base/common/process.ts | 2 +- src/vs/base/common/resources.ts | 2 +- src/vs/base/common/scrollable.ts | 12 +++--- src/vs/base/common/strings.ts | 36 ++++++++-------- src/vs/base/common/types.ts | 2 +- src/vs/base/common/uri.ts | 14 +++---- 29 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index ce2f41cf633..4b6e32dc042 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -51,8 +51,8 @@ export function binarySearch(array: ReadonlyArray, key: T, comparator: (op high = array.length - 1; while (low <= high) { - let mid = ((low + high) / 2) | 0; - let comp = comparator(array[mid], key); + const mid = ((low + high) / 2) | 0; + const comp = comparator(array[mid], key); if (comp < 0) { low = mid + 1; } else if (comp > 0) { @@ -75,7 +75,7 @@ export function findFirstInSorted(array: ReadonlyArray, p: (x: T) => boole return 0; // no children } while (low < high) { - let mid = Math.floor((low + high) / 2); + const mid = Math.floor((low + high) / 2); if (p(array[mid])) { high = mid; } else { @@ -122,7 +122,7 @@ function _sort(a: T[], compare: Compare, lo: number, hi: number, aux: T[]) if (hi <= lo) { return; } - let mid = lo + ((hi - lo) / 2) | 0; + const mid = lo + ((hi - lo) / 2) | 0; _sort(a, compare, lo, mid, aux); _sort(a, compare, mid + 1, hi, aux); if (compare(a[mid], a[mid + 1]) <= 0) { @@ -502,8 +502,8 @@ export function shuffle(array: T[], _seed?: number): void { } for (let i = array.length - 1; i > 0; i -= 1) { - let j = Math.floor(rand() * (i + 1)); - let temp = array[i]; + const j = Math.floor(rand() * (i + 1)); + const temp = array[i]; array[i] = array[j]; array[j] = temp; } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index 080a2c7a273..8cc8a36ffcd 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -52,7 +52,7 @@ export function createCancelablePromise(callback: (token: CancellationToken) export function asPromise(callback: () => T | Thenable): Promise { return new Promise((resolve, reject) => { - let item = callback(); + const item = callback(); if (isThenable(item)) { item.then(resolve, reject); } else { @@ -688,12 +688,12 @@ declare function cancelIdleCallback(handle: number): void; (function () { if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') { - let dummyIdle: IdleDeadline = Object.freeze({ + const dummyIdle: IdleDeadline = Object.freeze({ didTimeout: true, timeRemaining() { return 15; } }); runWhenIdle = (runner) => { - let handle = setTimeout(() => runner(dummyIdle)); + const handle = setTimeout(() => runner(dummyIdle)); let disposed = false; return { dispose() { @@ -707,7 +707,7 @@ declare function cancelIdleCallback(handle: number): void; }; } else { runWhenIdle = (runner, timeout?) => { - let handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); + const handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); let disposed = false; return { dispose() { diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index 39f672c9751..8f6b0b96f74 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -16,7 +16,7 @@ export interface CancellationToken { } const shortcutEvent = Object.freeze(function (callback, context?): IDisposable { - let handle = setTimeout(callback.bind(context), 0); + const handle = setTimeout(callback.bind(context), 0); return { dispose() { clearTimeout(handle); } }; } as Event); diff --git a/src/vs/base/common/color.ts b/src/vs/base/common/color.ts index f63e7aa86f1..3be7a1128a6 100644 --- a/src/vs/base/common/color.ts +++ b/src/vs/base/common/color.ts @@ -387,7 +387,7 @@ export class Color { const thisA = this.rgba.a; const colorA = rgba.a; - let a = thisA + colorA * (1 - thisA); + const a = thisA + colorA * (1 - thisA); if (a < 1e-6) { return Color.transparent; } diff --git a/src/vs/base/common/comparers.ts b/src/vs/base/common/comparers.ts index f5b9b26edd6..adf5859c794 100644 --- a/src/vs/base/common/comparers.ts +++ b/src/vs/base/common/comparers.ts @@ -144,8 +144,8 @@ export function comparePaths(one: string, other: string, caseSensitive = false): } export function compareAnything(one: string, other: string, lookFor: string): number { - let elementAName = one.toLowerCase(); - let elementBName = other.toLowerCase(); + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); // Sort prefix matches over non prefix matches const prefixCompare = compareByPrefix(one, other, lookFor); @@ -154,14 +154,14 @@ export function compareAnything(one: string, other: string, lookFor: string): nu } // Sort suffix matches over non suffix matches - let elementASuffixMatch = strings.endsWith(elementAName, lookFor); - let elementBSuffixMatch = strings.endsWith(elementBName, lookFor); + const elementASuffixMatch = strings.endsWith(elementAName, lookFor); + const elementBSuffixMatch = strings.endsWith(elementBName, lookFor); if (elementASuffixMatch !== elementBSuffixMatch) { return elementASuffixMatch ? -1 : 1; } // Understand file names - let r = compareFileNames(elementAName, elementBName); + const r = compareFileNames(elementAName, elementBName); if (r !== 0) { return r; } @@ -171,12 +171,12 @@ export function compareAnything(one: string, other: string, lookFor: string): nu } export function compareByPrefix(one: string, other: string, lookFor: string): number { - let elementAName = one.toLowerCase(); - let elementBName = other.toLowerCase(); + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); // Sort prefix matches over non prefix matches - let elementAPrefixMatch = strings.startsWith(elementAName, lookFor); - let elementBPrefixMatch = strings.startsWith(elementBName, lookFor); + const elementAPrefixMatch = strings.startsWith(elementAName, lookFor); + const elementBPrefixMatch = strings.startsWith(elementBName, lookFor); if (elementAPrefixMatch !== elementBPrefixMatch) { return elementAPrefixMatch ? -1 : 1; } diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index 15e2eb22b8b..da6f814332f 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -102,7 +102,7 @@ export function transformErrorForSerialization(error: any): any; export function transformErrorForSerialization(error: any): any { if (error instanceof Error) { let { name, message } = error; - let stack: string = (error).stacktrace || (error).stack; + const stack: string = (error).stacktrace || (error).stack; return { $isError: true, name, @@ -146,7 +146,7 @@ export function isPromiseCanceledError(error: any): boolean { * Returns an error that signals cancellation. */ export function canceled(): Error { - let error = new Error(canceledName); + const error = new Error(canceledName); error.name = error.message; return error; } diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 1a5596aa6b7..159c6e708d9 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -152,7 +152,7 @@ export namespace Event { clearTimeout(handle); handle = setTimeout(() => { - let _output = output; + const _output = output; output = undefined; handle = undefined; if (!leading || numDebouncedCalls > 1) { @@ -190,7 +190,7 @@ export namespace Event { let cache: T; return filter(event, value => { - let shouldEmit = firstCall || value !== cache; + const shouldEmit = firstCall || value !== cache; firstCall = false; cache = value; return shouldEmit; @@ -389,7 +389,7 @@ export interface EmitterOptions { let _globalLeakWarningThreshold = -1; export function setGlobalLeakWarningThreshold(n: number): IDisposable { - let oldValue = _globalLeakWarningThreshold; + const oldValue = _globalLeakWarningThreshold; _globalLeakWarningThreshold = n; return { dispose() { @@ -428,8 +428,8 @@ class LeakageMonitor { if (!this._stacks) { this._stacks = new Map(); } - let stack = new Error().stack!.split('\n').slice(3).join('\n'); - let count = (this._stacks.get(stack) || 0); + const stack = new Error().stack!.split('\n').slice(3).join('\n'); + const count = (this._stacks.get(stack) || 0); this._stacks.set(stack, count + 1); this._warnCountdown -= 1; @@ -453,7 +453,7 @@ class LeakageMonitor { } return () => { - let count = (this._stacks!.get(stack) || 0); + const count = (this._stacks!.get(stack) || 0); this._stacks!.set(stack, count - 1); }; } @@ -627,7 +627,7 @@ export class AsyncEmitter extends Emitter { } for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) { - let thenables: Promise[] = []; + const thenables: Promise[] = []; this._asyncDeliveryQueue.push([e.value, eventFn(thenables, typeof e.value === 'function' ? e.value : e.value[0]), thenables]); } diff --git a/src/vs/base/common/extpath.ts b/src/vs/base/common/extpath.ts index ab554f756bf..984a1c8afd1 100644 --- a/src/vs/base/common/extpath.ts +++ b/src/vs/base/common/extpath.ts @@ -32,7 +32,7 @@ export function getRoot(path: string, sep: string = posix.sep): string { return ''; } - let len = path.length; + const len = path.length; const firstLetter = path.charCodeAt(0); if (isPathSeparator(firstLetter)) { if (isPathSeparator(path.charCodeAt(1))) { @@ -40,7 +40,7 @@ export function getRoot(path: string, sep: string = posix.sep): string { // ^^^^^^^^^^^^^^^^^^^ if (!isPathSeparator(path.charCodeAt(2))) { let pos = 3; - let start = pos; + const start = pos; for (; pos < len; pos++) { if (isPathSeparator(path.charCodeAt(pos))) { break; @@ -121,7 +121,7 @@ export function isUNC(path: string): boolean { return false; } let pos = 2; - let start = pos; + const start = pos; for (; pos < path.length; pos++) { code = path.charCodeAt(pos); if (code === CharCode.Backslash) { diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index e7674b93648..ef1df908741 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -28,7 +28,7 @@ export interface IMatch { export function or(...filter: IFilter[]): IFilter { return function (word: string, wordToMatchAgainst: string): IMatch[] | null { for (let i = 0, len = filter.length; i < len; i++) { - let match = filter[i](word, wordToMatchAgainst); + const match = filter[i](word, wordToMatchAgainst); if (match) { return match; } @@ -64,7 +64,7 @@ function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: s // Contiguous Substring export function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { - let index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); + const index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); if (index === -1) { return null; } @@ -136,7 +136,7 @@ function join(head: IMatch, tail: IMatch[]): IMatch[] { function nextAnchor(camelCaseWord: string, start: number): number { for (let i = start; i < camelCaseWord.length; i++) { - let c = camelCaseWord.charCodeAt(i); + const c = camelCaseWord.charCodeAt(i); if (isUpper(c) || isNumber(c) || (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))) { return i; } @@ -184,10 +184,10 @@ function analyzeCamelCaseWord(word: string): ICamelCaseAnalysis { if (isNumber(code)) { numeric++; } } - let upperPercent = upper / word.length; - let lowerPercent = lower / word.length; - let alphaPercent = alpha / word.length; - let numericPercent = numeric / word.length; + const upperPercent = upper / word.length; + const lowerPercent = lower / word.length; + const alphaPercent = alpha / word.length; + const numericPercent = numeric / word.length; return { upperPercent, lowerPercent, alphaPercent, numericPercent }; } @@ -307,7 +307,7 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti function nextWord(word: string, start: number): number { for (let i = start; i < word.length; i++) { - let c = word.charCodeAt(i); + const c = word.charCodeAt(i); if (isWhitespace(c) || (i > 0 && isWhitespace(word.charCodeAt(i - 1)))) { return i; } @@ -334,7 +334,7 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep } // RegExp Filter - let match = regexp.exec(wordToMatchAgainst); + const match = regexp.exec(wordToMatchAgainst); if (match) { return [{ start: match.index, end: match.index + match[0].length }]; } @@ -348,7 +348,7 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep * powerfull than `matchesFuzzy` */ export function matchesFuzzy2(pattern: string, word: string): IMatch[] | null { - let score = fuzzyScore(pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, true); + const score = fuzzyScore(pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, true); return score ? createMatches(score) : null; } @@ -404,7 +404,7 @@ function initTable() { row.push(-i); } for (let i = 0; i <= _maxLen; i++) { - let thisRow = row.slice(0); + const thisRow = row.slice(0); thisRow[0] = -i; table.push(thisRow); } @@ -566,9 +566,9 @@ export function fuzzyScore(pattern: string, patternLow: string, patternPos: numb _scores[patternPos][wordPos] = score; - let diag = _table[patternPos - 1][wordPos - 1] + (score > 1 ? 1 : score); - let top = _table[patternPos - 1][wordPos] + -1; - let left = _table[patternPos][wordPos - 1] + -1; + const diag = _table[patternPos - 1][wordPos - 1] + (score > 1 ? 1 : score); + const top = _table[patternPos - 1][wordPos] + -1; + const left = _table[patternPos][wordPos - 1] + -1; if (left >= top) { // left or diag @@ -635,8 +635,8 @@ function _findAllMatches2(patternPos: number, wordPos: number, total: number, ma while (patternPos > _patternStartPos && wordPos > 0) { - let score = _scores[patternPos][wordPos]; - let arrow = _arrows[patternPos][wordPos]; + const score = _scores[patternPos][wordPos]; + const arrow = _arrows[patternPos][wordPos]; if (arrow === Arrow.Left) { // left -> no match, skip a word character @@ -733,11 +733,11 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // permutations of the pattern to find a better match. The // permutations only swap neighbouring characters, e.g // `cnoso` becomes `conso`, `cnsoo`, `cnoos`. - let tries = Math.min(7, pattern.length - 1); + const tries = Math.min(7, pattern.length - 1); for (let movingPatternPos = patternPos + 1; movingPatternPos < tries; movingPatternPos++) { - let newPattern = nextTypoPermutation(pattern, movingPatternPos); + const newPattern = nextTypoPermutation(pattern, movingPatternPos); if (newPattern) { - let candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); if (candidate) { candidate[0] -= 3; // permutation penalty if (!top || candidate[0] > top[0]) { @@ -757,8 +757,8 @@ function nextTypoPermutation(pattern: string, patternPos: number): string | unde return undefined; } - let swap1 = pattern[patternPos]; - let swap2 = pattern[patternPos + 1]; + const swap1 = pattern[patternPos]; + const swap2 = pattern[patternPos + 1]; if (swap1 === swap2) { return undefined; diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index a7569150a48..0cecf47d7d4 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -53,7 +53,7 @@ export function splitGlobAware(pattern: string, splitChar: string): string[] { return []; } - let segments: string[] = []; + const segments: string[] = []; let inBraces = false; let inBrackets = false; @@ -102,7 +102,7 @@ function parseRegExp(pattern: string): string { let regEx = ''; // Split up into segments for each slash found - let segments = splitGlobAware(pattern, GLOB_SPLIT); + const segments = splitGlobAware(pattern, GLOB_SPLIT); // Special case where we only have globstars if (segments.every(s => s === GLOBSTAR)) { @@ -179,10 +179,10 @@ function parseRegExp(pattern: string): string { continue; case '}': - let choices = splitGlobAware(braceVal, ','); + const choices = splitGlobAware(braceVal, ','); // Converts {foo,bar} => [foo|bar] - let braceRegExp = `(?:${choices.map(c => parseRegExp(c)).join('|')})`; + const braceRegExp = `(?:${choices.map(c => parseRegExp(c)).join('|')})`; regEx += braceRegExp; diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index 95551eb1a7a..19dada92a3e 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -66,7 +66,7 @@ export class HistoryNavigator implements INavigator { } private _reduceToLimit() { - let data = this._elements; + const data = this._elements; if (data.length > this._limit) { this._initialize(data.slice(data.length - this._limit)); } diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index e0cf131ad89..b3a62ede9ff 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -209,7 +209,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON let digits = 0; let value = 0; while (digits < count) { - let ch = text.charCodeAt(pos); + const ch = text.charCodeAt(pos); if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) { value = value * 16 + ch - CharacterCodes._0; } @@ -240,7 +240,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON } function scanNumber(): string { - let start = pos; + const start = pos; if (text.charCodeAt(pos) === CharacterCodes._0) { pos++; } else { @@ -331,7 +331,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON result += '\t'; break; case CharacterCodes.u: - let ch = scanHexDigits(4); + const ch = scanHexDigits(4); if (ch >= 0) { result += String.fromCharCode(ch); } else { @@ -424,7 +424,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON // comments case CharacterCodes.slash: - let start = pos - 1; + const start = pos - 1; // Single-line comment if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -444,10 +444,10 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - let safeLength = len - 1; // For lookahead. + const safeLength = len - 1; // For lookahead. let commentClosed = false; while (pos < safeLength) { - let ch = text.charCodeAt(pos); + const ch = text.charCodeAt(pos); if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -720,8 +720,8 @@ interface NodeImpl extends Node { * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index. */ export function getLocation(text: string, position: number): Location { - let segments: Segment[] = []; // strings or numbers - let earlyReturnException = new Object(); + const segments: Segment[] = []; // strings or numbers + const earlyReturnException = new Object(); let previousNode: NodeImpl | undefined = undefined; const previousNodeInst: NodeImpl = { value: {}, @@ -800,7 +800,7 @@ export function getLocation(text: string, position: number): Location { isAtPropertyKey = false; previousNode = undefined; } else if (sep === ',') { - let last = segments[segments.length - 1]; + const last = segments[segments.length - 1]; if (typeof last === 'number') { segments[segments.length - 1] = last + 1; } else { @@ -843,7 +843,7 @@ export function getLocation(text: string, position: number): Location { export function parse(text: string, errors: ParseError[] = [], options: ParseOptions = ParseOptions.DEFAULT): any { let currentProperty: string | null = null; let currentParent: any = []; - let previousParents: any[] = []; + const previousParents: any[] = []; function onValue(value: any) { if (Array.isArray(currentParent)) { @@ -853,9 +853,9 @@ export function parse(text: string, errors: ParseError[] = [], options: ParseOpt } } - let visitor: JSONVisitor = { + const visitor: JSONVisitor = { onObjectBegin: () => { - let object = {}; + const object = {}; onValue(object); previousParents.push(currentParent); currentParent = object; @@ -868,7 +868,7 @@ export function parse(text: string, errors: ParseError[] = [], options: ParseOpt currentParent = previousParents.pop(); }, onArrayBegin: () => { - let array: any[] = []; + const array: any[] = []; onValue(array); previousParents.push(currentParent); currentParent = array; @@ -905,7 +905,7 @@ export function parseTree(text: string, errors: ParseError[] = [], options: Pars return valueNode; } - let visitor: JSONVisitor = { + const visitor: JSONVisitor = { onObjectBegin: (offset: number) => { currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] }); }, @@ -945,7 +945,7 @@ export function parseTree(text: string, errors: ParseError[] = [], options: Pars }; visit(text, visitor, options); - let result = currentParent.children![0]; + const result = currentParent.children![0]; if (result) { delete result.parent; } @@ -977,7 +977,7 @@ export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined return undefined; } } else { - let index = segment; + const index = segment; if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) { return undefined; } @@ -994,12 +994,12 @@ export function getNodePath(node: Node): JSONPath { if (!node.parent || !node.parent.children) { return []; } - let path = getNodePath(node.parent); + const path = getNodePath(node.parent); if (node.parent.type === 'property') { - let key = node.parent.children[0].value; + const key = node.parent.children[0].value; path.push(key); } else if (node.parent.type === 'array') { - let index = node.parent.children.indexOf(node); + const index = node.parent.children.indexOf(node); if (index !== -1) { path.push(index); } @@ -1015,9 +1015,9 @@ export function getNodeValue(node: Node): any { case 'array': return node.children!.map(getNodeValue); case 'object': - let obj = Object.create(null); + const obj = Object.create(null); for (let prop of node.children!) { - let valueNode = prop.children![1]; + const valueNode = prop.children![1]; if (valueNode) { obj[prop.children![0].value] = getNodeValue(valueNode); } @@ -1043,10 +1043,10 @@ export function contains(node: Node, offset: number, includeRightBound = false): */ export function findNodeAtOffset(node: Node, offset: number, includeRightBound = false): Node | undefined { if (contains(node, offset, includeRightBound)) { - let children = node.children; + const children = node.children; if (Array.isArray(children)) { for (let i = 0; i < children.length && children[i].offset <= offset; i++) { - let item = findNodeAtOffset(children[i], offset, includeRightBound); + const item = findNodeAtOffset(children[i], offset, includeRightBound); if (item) { return item; } @@ -1064,7 +1064,7 @@ export function findNodeAtOffset(node: Node, offset: number, includeRightBound = */ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions = ParseOptions.DEFAULT): any { - let _scanner = createScanner(text, false); + const _scanner = createScanner(text, false); function toNoArgVisit(visitFunction?: (offset: number, length: number) => void): () => void { return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; @@ -1073,7 +1073,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; } - let onObjectBegin = toNoArgVisit(visitor.onObjectBegin), + const onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), @@ -1083,11 +1083,11 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError); - let disallowComments = options && options.disallowComments; - let allowTrailingComma = options && options.allowTrailingComma; + const disallowComments = options && options.disallowComments; + const allowTrailingComma = options && options.allowTrailingComma; function scanNext(): SyntaxKind { while (true) { - let token = _scanner.scan(); + const token = _scanner.scan(); switch (_scanner.getTokenError()) { case ScanError.InvalidUnicode: handleError(ParseErrorCode.InvalidUnicode); @@ -1148,7 +1148,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions } function parseString(isValue: boolean): boolean { - let value = _scanner.getTokenValue(); + const value = _scanner.getTokenValue(); if (isValue) { onLiteralValue(value); } else { diff --git a/src/vs/base/common/jsonEdit.ts b/src/vs/base/common/jsonEdit.ts index 7675ea16049..4a99bee9acd 100644 --- a/src/vs/base/common/jsonEdit.ts +++ b/src/vs/base/common/jsonEdit.ts @@ -12,9 +12,9 @@ export function removeProperty(text: string, path: JSONPath, formattingOptions: } export function setProperty(text: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number): Edit[] { - let path = originalPath.slice(); - let errors: ParseError[] = []; - let root = parseTree(text, errors); + const path = originalPath.slice(); + const errors: ParseError[] = []; + const root = parseTree(text, errors); let parent: Node | undefined = undefined; let lastSegment: Segment | undefined = undefined; @@ -39,24 +39,24 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo } return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, formattingOptions); } else if (parent.type === 'object' && typeof lastSegment === 'string' && Array.isArray(parent.children)) { - let existing = findNodeAtLocation(parent, [lastSegment]); + const existing = findNodeAtLocation(parent, [lastSegment]); if (existing !== undefined) { if (value === undefined) { // delete if (!existing.parent) { throw new Error('Malformed AST'); } - let propertyIndex = parent.children.indexOf(existing.parent); + const propertyIndex = parent.children.indexOf(existing.parent); let removeBegin: number; let removeEnd = existing.parent.offset + existing.parent.length; if (propertyIndex > 0) { // remove the comma of the previous node - let previous = parent.children[propertyIndex - 1]; + const previous = parent.children[propertyIndex - 1]; removeBegin = previous.offset + previous.length; } else { removeBegin = parent.offset + 1; if (parent.children.length > 1) { // remove the comma of the next node - let next = parent.children[1]; + const next = parent.children[1]; removeEnd = next.offset; } } @@ -69,11 +69,11 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo if (value === undefined) { // delete return []; // property does not exist, nothing to do } - let newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`; - let index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children![0].value)) : parent.children.length; + const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`; + const index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children![0].value)) : parent.children.length; let edit: Edit; if (index > 0) { - let previous = parent.children[index - 1]; + const previous = parent.children[index - 1]; edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty }; } else if (parent.children.length === 0) { edit = { offset: parent.offset + 1, length: 0, content: newProperty }; @@ -83,32 +83,32 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo return withFormatting(text, edit, formattingOptions); } } else if (parent.type === 'array' && typeof lastSegment === 'number' && Array.isArray(parent.children)) { - let insertIndex = lastSegment; + const insertIndex = lastSegment; if (insertIndex === -1) { // Insert - let newProperty = `${JSON.stringify(value)}`; + const newProperty = `${JSON.stringify(value)}`; let edit: Edit; if (parent.children.length === 0) { edit = { offset: parent.offset + 1, length: 0, content: newProperty }; } else { - let previous = parent.children[parent.children.length - 1]; + const previous = parent.children[parent.children.length - 1]; edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty }; } return withFormatting(text, edit, formattingOptions); } else { if (value === undefined && parent.children.length >= 0) { //Removal - let removalIndex = lastSegment; - let toRemove = parent.children[removalIndex]; + const removalIndex = lastSegment; + const toRemove = parent.children[removalIndex]; let edit: Edit; if (parent.children.length === 1) { // only item edit = { offset: parent.offset + 1, length: parent.length - 2, content: '' }; } else if (parent.children.length - 1 === removalIndex) { // last item - let previous = parent.children[removalIndex - 1]; - let offset = previous.offset + previous.length; - let parentEndOffset = parent.offset + parent.length; + const previous = parent.children[removalIndex - 1]; + const offset = previous.offset + previous.length; + const parentEndOffset = parent.offset + parent.length; edit = { offset, length: parentEndOffset - 2 - offset, content: '' }; } else { edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: '' }; @@ -139,18 +139,18 @@ function withFormatting(text: string, edit: Edit, formattingOptions: FormattingO } } - let edits = format(newText, { offset: begin, length: end - begin }, formattingOptions); + const edits = format(newText, { offset: begin, length: end - begin }, formattingOptions); // apply the formatting edits and track the begin and end offsets of the changes for (let i = edits.length - 1; i >= 0; i--) { - let edit = edits[i]; + const edit = edits[i]; newText = applyEdit(newText, edit); begin = Math.min(begin, edit.offset); end = Math.max(end, edit.offset + edit.length); end += edit.content.length - edit.length; } // create a single edit with all changes - let editLength = text.length - (newText.length - end) - begin; + const editLength = text.length - (newText.length - end) - begin; return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }]; } diff --git a/src/vs/base/common/jsonFormatter.ts b/src/vs/base/common/jsonFormatter.ts index df2a97ee5cd..a25c493c05d 100644 --- a/src/vs/base/common/jsonFormatter.ts +++ b/src/vs/base/common/jsonFormatter.ts @@ -80,7 +80,7 @@ export function format(documentText: string, range: Range | undefined, options: rangeStart = 0; rangeEnd = documentText.length; } - let eol = getEOL(options, documentText); + const eol = getEOL(options, documentText); let lineBreak = false; let indentLevel = 0; @@ -91,7 +91,7 @@ export function format(documentText: string, range: Range | undefined, options: indentValue = '\t'; } - let scanner = createScanner(formatText, false); + const scanner = createScanner(formatText, false); let hasError = false; function newLineAndIndent(): string { @@ -107,7 +107,7 @@ export function format(documentText: string, range: Range | undefined, options: hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None; return token; } - let editOperations: Edit[] = []; + const editOperations: Edit[] = []; function addEdit(text: string, startOffset: number, endOffset: number) { if (!hasError && startOffset < rangeEnd && endOffset > rangeStart && documentText.substring(startOffset, endOffset) !== text) { editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text }); @@ -117,8 +117,8 @@ export function format(documentText: string, range: Range | undefined, options: let firstToken = scanNext(); if (firstToken !== SyntaxKind.EOF) { - let firstTokenStart = scanner.getTokenOffset() + formatTextStart; - let initialIndent = repeat(indentValue, initialIndentLevel); + const firstTokenStart = scanner.getTokenOffset() + formatTextStart; + const initialIndent = repeat(indentValue, initialIndentLevel); addEdit(initialIndent, formatTextStart, firstTokenStart); } @@ -129,7 +129,7 @@ export function format(documentText: string, range: Range | undefined, options: let replaceContent = ''; while (!lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) { // comments on the same line: keep them on the same line, but ignore them otherwise - let commentTokenStart = scanner.getTokenOffset() + formatTextStart; + const commentTokenStart = scanner.getTokenOffset() + formatTextStart; addEdit(' ', firstTokenEnd, commentTokenStart); firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart; replaceContent = secondToken === SyntaxKind.LineCommentTrivia ? newLineAndIndent() : ''; @@ -195,7 +195,7 @@ export function format(documentText: string, range: Range | undefined, options: } } - let secondTokenStart = scanner.getTokenOffset() + formatTextStart; + const secondTokenStart = scanner.getTokenOffset() + formatTextStart; addEdit(replaceContent, firstTokenEnd, secondTokenStart); firstToken = secondToken; } @@ -213,9 +213,9 @@ function repeat(s: string, count: number): string { function computeIndentLevel(content: string, options: FormattingOptions): number { let i = 0; let nChars = 0; - let tabSize = options.tabSize || 4; + const tabSize = options.tabSize || 4; while (i < content.length) { - let ch = content.charAt(i); + const ch = content.charAt(i); if (ch === ' ') { nChars++; } else if (ch === '\t') { @@ -230,7 +230,7 @@ function computeIndentLevel(content: string, options: FormattingOptions): number function getEOL(options: FormattingOptions, text: string): string { for (let i = 0; i < text.length; i++) { - let ch = text.charAt(i); + const ch = text.charAt(i); if (ch === '\r') { if (i + 1 < text.length && text.charAt(i + 1) === '\n') { return '\r\n'; diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index b2d75920a4c..ec08bea7e91 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -407,7 +407,7 @@ export const enum KeyMod { } export function KeyChord(firstPart: number, secondPart: number): number { - let chordPart = ((secondPart & 0x0000FFFF) << 16) >>> 0; + const chordPart = ((secondPart & 0x0000FFFF) << 16) >>> 0; return (firstPart | chordPart) >>> 0; } @@ -466,10 +466,10 @@ export class SimpleKeybinding { } public getHashCode(): string { - let ctrl = this.ctrlKey ? '1' : '0'; - let shift = this.shiftKey ? '1' : '0'; - let alt = this.altKey ? '1' : '0'; - let meta = this.metaKey ? '1' : '0'; + const ctrl = this.ctrlKey ? '1' : '0'; + const shift = this.shiftKey ? '1' : '0'; + const alt = this.altKey ? '1' : '0'; + const meta = this.metaKey ? '1' : '0'; return `${ctrl}${shift}${alt}${meta}${this.keyCode}`; } diff --git a/src/vs/base/common/keybindingLabels.ts b/src/vs/base/common/keybindingLabels.ts index a1df76ab4fb..671816830bd 100644 --- a/src/vs/base/common/keybindingLabels.ts +++ b/src/vs/base/common/keybindingLabels.ts @@ -41,7 +41,7 @@ export class ModifierLabelProvider { return null; } - let result: string[] = []; + const result: string[] = []; for (let i = 0, len = parts.length; i < len; i++) { const part = parts[i]; const keyLabel = keyLabelProvider(part); @@ -162,7 +162,7 @@ function _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabe return ''; } - let result: string[] = []; + const result: string[] = []; // translate modifier keys: Ctrl-Shift-Alt-Meta if (modifiers.ctrlKey) { diff --git a/src/vs/base/common/keybindingParser.ts b/src/vs/base/common/keybindingParser.ts index 68025d9131b..f7e120acc53 100644 --- a/src/vs/base/common/keybindingParser.ts +++ b/src/vs/base/common/keybindingParser.ts @@ -85,7 +85,7 @@ export class KeybindingParser { return null; } - let parts: SimpleKeybinding[] = []; + const parts: SimpleKeybinding[] = []; let part: SimpleKeybinding; do { @@ -112,7 +112,7 @@ export class KeybindingParser { return []; } - let parts: (SimpleKeybinding | ScanCodeBinding)[] = []; + const parts: (SimpleKeybinding | ScanCodeBinding)[] = []; let part: SimpleKeybinding | ScanCodeBinding; while (input.length > 0) { diff --git a/src/vs/base/common/linkedList.ts b/src/vs/base/common/linkedList.ts index 5673ae64808..0eb16c2faa3 100644 --- a/src/vs/base/common/linkedList.ts +++ b/src/vs/base/common/linkedList.ts @@ -97,7 +97,7 @@ export class LinkedList { } if (candidate.prev && candidate.next) { // middle - let anchor = candidate.prev; + const anchor = candidate.prev; anchor.next = candidate.next; candidate.next.prev = anchor; @@ -144,7 +144,7 @@ export class LinkedList { } toArray(): E[] { - let result: E[] = []; + const result: E[] = []; for (let node = this._first; node instanceof Node; node = node.next) { result.push(node.element); } diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index c1ed1d4aa4a..5320086b024 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -100,8 +100,8 @@ export class StringIterator implements IKeyIterator { } cmp(a: string): number { - let aCode = a.charCodeAt(0); - let thisCode = this._value.charCodeAt(this._pos); + const aCode = a.charCodeAt(0); + const thisCode = this._value.charCodeAt(this._pos); return aCode - thisCode; } @@ -149,11 +149,11 @@ export class PathIterator implements IKeyIterator { cmp(a: string): number { let aPos = 0; - let aLen = a.length; + const aLen = a.length; let thisPos = this._from; while (aPos < aLen && thisPos < this._to) { - let cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos); + const cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos); if (cmp !== 0) { return cmp; } @@ -210,7 +210,7 @@ export class TernarySearchTree { } set(key: string, element: E): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node: TernarySearchTreeNode; if (!this._root) { @@ -220,7 +220,7 @@ export class TernarySearchTree { node = this._root; while (true) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left if (!node.left) { @@ -256,10 +256,10 @@ export class TernarySearchTree { } get(key: string): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -279,13 +279,13 @@ export class TernarySearchTree { delete(key: string): void { - let iter = this._iter.reset(key); - let stack: [-1 | 0 | 1, TernarySearchTreeNode][] = []; + const iter = this._iter.reset(key); + const stack: [-1 | 0 | 1, TernarySearchTreeNode][] = []; let node = this._root; // find and unset node while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left stack.push([1, node]); @@ -319,11 +319,11 @@ export class TernarySearchTree { } findSubstr(key: string): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; let candidate: E | undefined = undefined; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -343,10 +343,10 @@ export class TernarySearchTree { } findSuperstr(key: string): Iterator | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -373,7 +373,7 @@ export class TernarySearchTree { let res: { done: false; value: E; }; let idx: number; let data: E[]; - let next = (): IteratorResult => { + const next = (): IteratorResult => { if (!data) { // lazy till first invocation data = []; @@ -610,7 +610,7 @@ export class LinkedMap { } values(): V[] { - let result: V[] = []; + const result: V[] = []; let current = this._head; while (current) { result.push(current.value); @@ -620,7 +620,7 @@ export class LinkedMap { } keys(): K[] { - let result: K[] = []; + const result: K[] = []; let current = this._head; while (current) { result.push(current.key); @@ -631,14 +631,14 @@ export class LinkedMap { /* VS Code / Monaco editor runs on es5 which has no Symbol.iterator keys(): IterableIterator { - let current = this._head; - let iterator: IterableIterator = { + const current = this._head; + const iterator: IterableIterator = { [Symbol.iterator]() { return iterator; }, next():IteratorResult { if (current) { - let result = { value: current.key, done: false }; + const result = { value: current.key, done: false }; current = current.next; return result; } else { @@ -650,14 +650,14 @@ export class LinkedMap { } values(): IterableIterator { - let current = this._head; - let iterator: IterableIterator = { + const current = this._head; + const iterator: IterableIterator = { [Symbol.iterator]() { return iterator; }, next():IteratorResult { if (current) { - let result = { value: current.value, done: false }; + const result = { value: current.value, done: false }; current = current.next; return result; } else { diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index ef5e8b59de4..34e9a7862c9 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -30,11 +30,11 @@ export function deepFreeze(obj: T): T { } const stack: any[] = [obj]; while (stack.length > 0) { - let obj = stack.shift(); + const obj = stack.shift(); Object.freeze(obj); for (const key in obj) { if (_hasOwnProperty.call(obj, key)) { - let prop = obj[key]; + const prop = obj[key]; if (typeof prop === 'object' && !Object.isFrozen(prop)) { stack.push(prop); } diff --git a/src/vs/base/common/parsers.ts b/src/vs/base/common/parsers.ts index da9010662fa..4ea4e95373d 100644 --- a/src/vs/base/common/parsers.ts +++ b/src/vs/base/common/parsers.ts @@ -81,8 +81,8 @@ export abstract class Parser { protected static merge(destination: T, source: T, overwrite: boolean): void { Object.keys(source).forEach((key: string) => { - let destValue = destination[key]; - let sourceValue = source[key]; + const destValue = destination[key]; + const sourceValue = source[key]; if (Types.isUndefined(sourceValue)) { return; } diff --git a/src/vs/base/common/path.ts b/src/vs/base/common/path.ts index 844cdd246a9..640c033ae01 100644 --- a/src/vs/base/common/path.ts +++ b/src/vs/base/common/path.ts @@ -231,7 +231,7 @@ export const win32: IPath = { continue; } - let len = path.length; + const len = path.length; let rootEnd = 0; let device = ''; let isAbsolute = false; @@ -503,7 +503,7 @@ export const win32: IPath = { let joined; let firstPart; for (let i = 0; i < paths.length; ++i) { - let arg = paths[i]; + const arg = paths[i]; validateString(arg, 'path'); if (arg.length > 0) { if (joined === undefined) { @@ -582,8 +582,8 @@ export const win32: IPath = { return ''; } - let fromOrig = win32.resolve(from); - let toOrig = win32.resolve(to); + const fromOrig = win32.resolve(from); + const toOrig = win32.resolve(to); if (fromOrig === toOrig) { return ''; @@ -610,7 +610,7 @@ export const win32: IPath = { break; } } - let fromLen = (fromEnd - fromStart); + const fromLen = (fromEnd - fromStart); // Trim any leading backslashes let toStart = 0; @@ -626,10 +626,10 @@ export const win32: IPath = { break; } } - let toLen = (toEnd - toStart); + const toLen = (toEnd - toStart); // Compare paths to find the longest common path from root - let length = (fromLen < toLen ? fromLen : toLen); + const length = (fromLen < toLen ? fromLen : toLen); let lastCommonSep = -1; let i = 0; for (; i <= length; ++i) { @@ -658,8 +658,8 @@ export const win32: IPath = { } break; } - let fromCode = from.charCodeAt(fromStart + i); - let toCode = to.charCodeAt(toStart + i); + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) { break; } @@ -1015,12 +1015,12 @@ export const win32: IPath = { parse(path) { validateString(path, 'path'); - let ret = { root: '', dir: '', base: '', ext: '', name: '' }; + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) { return ret; } - let len = path.length; + const len = path.length; let rootEnd = 0; let code = path.charCodeAt(0); @@ -1268,7 +1268,7 @@ export const posix: IPath = { } let joined; for (let i = 0; i < paths.length; ++i) { - let arg = arguments[i]; + const arg = arguments[i]; validateString(arg, 'path'); if (arg.length > 0) { if (joined === undefined) { @@ -1307,8 +1307,8 @@ export const posix: IPath = { break; } } - let fromEnd = from.length; - let fromLen = (fromEnd - fromStart); + const fromEnd = from.length; + const fromLen = (fromEnd - fromStart); // Trim any leading backslashes let toStart = 1; @@ -1317,11 +1317,11 @@ export const posix: IPath = { break; } } - let toEnd = to.length; - let toLen = (toEnd - toStart); + const toEnd = to.length; + const toLen = (toEnd - toStart); // Compare paths to find the longest common path from root - let length = (fromLen < toLen ? fromLen : toLen); + const length = (fromLen < toLen ? fromLen : toLen); let lastCommonSep = -1; let i = 0; for (; i <= length; ++i) { @@ -1349,8 +1349,8 @@ export const posix: IPath = { } break; } - let fromCode = from.charCodeAt(fromStart + i); - let toCode = to.charCodeAt(toStart + i); + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) { break; } @@ -1568,11 +1568,11 @@ export const posix: IPath = { parse(path: string): ParsedPath { validateString(path, 'path'); - let ret = { root: '', dir: '', base: '', ext: '', name: '' }; + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) { return ret; } - let isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; let start; if (isAbsolute) { ret.root = '/'; diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 6755ebaa983..66178dacef8 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -34,15 +34,15 @@ interface INodeProcess { }; type?: string; } -declare let process: INodeProcess; -declare let global: any; +declare const process: INodeProcess; +declare const global: any; interface INavigator { userAgent: string; language: string; } -declare let navigator: INavigator; -declare let self: any; +declare const navigator: INavigator; +declare const self: any; const isElectronRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined' && process.type === 'renderer'); diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts index 386ad29df56..a8447d58eea 100644 --- a/src/vs/base/common/process.ts +++ b/src/vs/base/common/process.ts @@ -13,7 +13,7 @@ interface IProcess { nextTick(callback: (...args: any[]) => void): number; } -declare let process: IProcess; +declare const process: IProcess; const safeProcess: IProcess = (typeof process === 'undefined') ? { cwd(): string { return '/'; }, env: Object.create(null), diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 54f46ad9468..60a58363f18 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -181,7 +181,7 @@ export function hasTrailingPathSeparator(resource: URI): boolean { const fsp = originalFSPath(resource); return fsp.length > extpath.getRoot(fsp).length && fsp[fsp.length - 1] === paths.sep; } else { - let p = resource.path; + const p = resource.path; return p.length > 1 && p.charCodeAt(p.length - 1) === CharCode.Slash; // ignore the slash at offset 0 } } diff --git a/src/vs/base/common/scrollable.ts b/src/vs/base/common/scrollable.ts index f33897a9f3b..1ecdd316ba8 100644 --- a/src/vs/base/common/scrollable.ts +++ b/src/vs/base/common/scrollable.ts @@ -117,13 +117,13 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { } public createScrollEvent(previous: ScrollState): ScrollEvent { - let widthChanged = (this.width !== previous.width); - let scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); - let scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); + const widthChanged = (this.width !== previous.width); + const scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); + const scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); - let heightChanged = (this.height !== previous.height); - let scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); - let scrollTopChanged = (this.scrollTop !== previous.scrollTop); + const heightChanged = (this.height !== previous.height); + const scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); + const scrollTopChanged = (this.scrollTop !== previous.scrollTop); return { width: this.width, diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index 72a0c0785b5..37c57c26f1c 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -21,8 +21,8 @@ export function isFalsyOrWhitespace(str: string | undefined): boolean { * @returns the provided number with the given number of preceding zeros. */ export function pad(n: number, l: number, char: string = '0'): string { - let str = '' + n; - let r = [str]; + const str = '' + n; + const r = [str]; for (let i = str.length; i < l; i++) { r.push(char); @@ -44,7 +44,7 @@ export function format(value: string, ...args: any[]): string { return value; } return value.replace(_formatRegexp, function (match, group) { - let idx = parseInt(group, 10); + const idx = parseInt(group, 10); return isNaN(idx) || idx < 0 || idx >= args.length ? match : args[idx]; @@ -79,7 +79,7 @@ export function escapeRegExpCharacters(value: string): string { * @param needle the thing to trim (default is a blank) */ export function trim(haystack: string, needle: string = ' '): string { - let trimmed = ltrim(haystack, needle); + const trimmed = ltrim(haystack, needle); return rtrim(trimmed, needle); } @@ -93,7 +93,7 @@ export function ltrim(haystack: string, needle: string): string { return haystack; } - let needleLen = needle.length; + const needleLen = needle.length; if (needleLen === 0 || haystack.length === 0) { return haystack; } @@ -116,7 +116,7 @@ export function rtrim(haystack: string, needle: string): string { return haystack; } - let needleLen = needle.length, + const needleLen = needle.length, haystackLen = haystack.length; if (needleLen === 0 || haystackLen === 0) { @@ -173,7 +173,7 @@ export function startsWith(haystack: string, needle: string): boolean { * Determines if haystack ends with needle. */ export function endsWith(haystack: string, needle: string): boolean { - let diff = haystack.length - needle.length; + const diff = haystack.length - needle.length; if (diff > 0) { return haystack.indexOf(needle, diff) === diff; } else if (diff === 0) { @@ -232,7 +232,7 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean { // We check against an empty string. If the regular expression doesn't advance // (e.g. ends in an endless loop) it will match an empty string. - let match = regexp.exec(''); + const match = regexp.exec(''); return !!(match && regexp.lastIndex === 0); } @@ -253,7 +253,7 @@ export function regExpFlags(regexp: RegExp): string { */ export function firstNonWhitespaceIndex(str: string): number { for (let i = 0, len = str.length; i < len; i++) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return i; } @@ -267,7 +267,7 @@ export function firstNonWhitespaceIndex(str: string): number { */ export function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string { for (let i = start; i < end; i++) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return str.substring(start, i); } @@ -281,7 +281,7 @@ export function getLeadingWhitespace(str: string, start: number = 0, end: number */ export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number { for (let i = startIndex; i >= 0; i--) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return i; } @@ -380,7 +380,7 @@ function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean { // a-z A-Z if (isAsciiLetter(codeA) && isAsciiLetter(codeB)) { - let diff = Math.abs(codeA - codeB); + const diff = Math.abs(codeA - codeB); if (diff !== 0 && diff !== 32) { return false; } @@ -431,8 +431,8 @@ export function commonSuffixLength(a: string, b: string): number { let i: number, len = Math.min(a.length, b.length); - let aLastIndex = a.length - 1; - let bLastIndex = b.length - 1; + const aLastIndex = a.length - 1; + const bLastIndex = b.length - 1; for (i = 0; i < len; i++) { if (a.charCodeAt(aLastIndex - i) !== b.charCodeAt(bLastIndex - i)) { @@ -459,7 +459,7 @@ function substrEquals(a: string, aStart: number, aEnd: number, b: string, bStart * For instance `overlap("foobar", "arr, I'm a pirate") === 2`. */ export function overlap(a: string, b: string): number { - let aEnd = a.length; + const aEnd = a.length; let bEnd = b.length; let aStart = aEnd - bEnd; @@ -486,9 +486,9 @@ export function overlap(a: string, b: string): number { // Code points U+0000 to U+D7FF and U+E000 to U+FFFF are represented on a single character // Code points U+10000 to U+10FFFF are represented on two consecutive characters //export function getUnicodePoint(str:string, index:number, len:number):number { -// let chrCode = str.charCodeAt(index); +// const chrCode = str.charCodeAt(index); // if (0xD800 <= chrCode && chrCode <= 0xDBFF && index + 1 < len) { -// let nextChrCode = str.charCodeAt(index + 1); +// const nextChrCode = str.charCodeAt(index + 1); // if (0xDC00 <= nextChrCode && nextChrCode <= 0xDFFF) { // return (chrCode - 0xD800) << 10 + (nextChrCode - 0xDC00) + 0x10000; // } @@ -685,7 +685,7 @@ export function fuzzyContains(target: string, query: string): boolean { let index = 0; let lastIndexOf = -1; while (index < queryLen) { - let indexOf = targetLower.indexOf(query[index], lastIndexOf + 1); + const indexOf = targetLower.indexOf(query[index], lastIndexOf + 1); if (indexOf < 0) { return false; } diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 9dbae8ce1e2..d2a261fb029 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -168,7 +168,7 @@ export function create(ctor: Function, ...args: any[]): any { if (isNativeClass(ctor)) { return new (ctor as any)(...args); } else { - let obj = Object.create(ctor.prototype); + const obj = Object.create(ctor.prototype); ctor.apply(obj, args); return obj; } diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 8fbecabfd80..79560531ae8 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -329,7 +329,7 @@ export class URI implements UriComponents { // check for authority as used in UNC shares // or use the path as given if (path[0] === _slash && path[1] === _slash) { - let idx = path.indexOf(_slash, 2); + const idx = path.indexOf(_slash, 2); if (idx === -1) { authority = path.substring(2); path = _slash; @@ -379,7 +379,7 @@ export class URI implements UriComponents { } else if (data instanceof URI) { return data; } else { - let result = new _URI(data); + const result = new _URI(data); result._fsPath = (data).fsPath; result._formatted = (data).external; return result; @@ -488,7 +488,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri let nativeEncodePos = -1; for (let pos = 0; pos < uriComponent.length; pos++) { - let code = uriComponent.charCodeAt(pos); + const code = uriComponent.charCodeAt(pos); // unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3 if ( @@ -518,7 +518,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri } // check with default table first - let escaped = encodeTable[code]; + const escaped = encodeTable[code]; if (escaped !== undefined) { // check if we are delaying native encode @@ -547,7 +547,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri function encodeURIComponentMinimal(path: string): string { let res: string | undefined = undefined; for (let pos = 0; pos < path.length; pos++) { - let code = path.charCodeAt(pos); + const code = path.charCodeAt(pos); if (code === CharCode.Hash || code === CharCode.QuestionMark) { if (res === undefined) { res = path.substr(0, pos); @@ -637,12 +637,12 @@ function _asFormatted(uri: URI, skipEncoding: boolean): string { if (path) { // lower-case windows drive letters in /C:/fff or C:/fff if (path.length >= 3 && path.charCodeAt(0) === CharCode.Slash && path.charCodeAt(2) === CharCode.Colon) { - let code = path.charCodeAt(1); + const code = path.charCodeAt(1); if (code >= CharCode.A && code <= CharCode.Z) { path = `/${String.fromCharCode(code + 32)}:${path.substr(3)}`; // "/c:".length === 3 } } else if (path.length >= 2 && path.charCodeAt(1) === CharCode.Colon) { - let code = path.charCodeAt(0); + const code = path.charCodeAt(0); if (code >= CharCode.A && code <= CharCode.Z) { path = `${String.fromCharCode(code + 32)}:${path.substr(2)}`; // "/c:".length === 3 } From 608fc2cee2f1a4c832d8c23b9d4e28805ddf6041 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 16:53:02 -0800 Subject: [PATCH 133/172] Auto convert let -> const in base/node --- src/vs/base/node/decoder.ts | 6 ++--- src/vs/base/node/flow.ts | 12 +++++----- src/vs/base/node/ports.ts | 4 ++-- src/vs/base/node/processes.ts | 44 +++++++++++++++++------------------ src/vs/base/node/ps.ts | 4 ++-- src/vs/base/node/request.ts | 2 +- src/vs/base/node/stats.ts | 22 +++++++++--------- src/vs/base/node/stream.ts | 2 +- src/vs/base/node/zip.ts | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/vs/base/node/decoder.ts b/src/vs/base/node/decoder.ts index 5ef4abf19f7..76741a370e4 100644 --- a/src/vs/base/node/decoder.ts +++ b/src/vs/base/node/decoder.ts @@ -24,8 +24,8 @@ export class LineDecoder { } public write(buffer: Buffer): string[] { - let result: string[] = []; - let value = this.remaining + const result: string[] = []; + const value = this.remaining ? this.remaining + this.stringDecoder.write(buffer) : this.stringDecoder.write(buffer); @@ -41,7 +41,7 @@ export class LineDecoder { result.push(value.substring(start, idx)); idx++; if (idx < value.length) { - let lastChar = ch; + const lastChar = ch; ch = value.charCodeAt(idx); if ((lastChar === CharCode.CarriageReturn && ch === CharCode.LineFeed) || (lastChar === CharCode.LineFeed && ch === CharCode.CarriageReturn)) { idx++; diff --git a/src/vs/base/node/flow.ts b/src/vs/base/node/flow.ts index c1232c2993b..a97727ae88d 100644 --- a/src/vs/base/node/flow.ts +++ b/src/vs/base/node/flow.ts @@ -10,8 +10,8 @@ import * as assert from 'assert'; * array to the callback (callback). The resulting errors and results are evaluated by calling the provided callback function. */ export function parallel(list: T[], fn: (item: T, callback: (err: Error | null, result: E | null) => void) => void, callback: (err: Array | null, result: E[]) => void): void { - let results = new Array(list.length); - let errors = new Array(list.length); + const results = new Array(list.length); + const errors = new Array(list.length); let didErrorOccur = false; let doneCount = 0; @@ -68,9 +68,9 @@ export function loop(param: any, fn: (item: any, callback: (error: Error | nu // Expect the param to be an array and loop over it else { - let results: E[] = []; + const results: E[] = []; - let looper: (i: number) => void = function (i: number): void { + const looper: (i: number) => void = function (i: number): void { // Still work to do if (i < param.length) { @@ -126,11 +126,11 @@ function Sequence(sequences: { (...param: any[]): void; }[]): void { }); // Execute in Loop - let errorHandler = sequences.splice(0, 1)[0]; //Remove error handler + const errorHandler = sequences.splice(0, 1)[0]; //Remove error handler let sequenceResult: any = null; loop(sequences, (sequence, clb) => { - let sequenceFunction = function (error: any, result: any): void { + const sequenceFunction = function (error: any, result: any): void { // A method might only send a boolean value as return value (e.g. fs.exists), support this case gracefully if (error === true || error === false) { diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index a077f020fa9..d0334628e47 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -9,8 +9,8 @@ import * as net from 'net'; * @returns Returns a random port between 1025 and 65535. */ export function randomPort(): number { - let min = 1025; - let max = 65535; + const min = 1025; + const max = 65535; return min + Math.floor((max - min) * Math.random()); } diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 9836e6ccfbb..df8690d0011 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -42,7 +42,7 @@ function getWindowsCode(status: number): TerminateResponseCode { export function terminateProcess(process: cp.ChildProcess, cwd?: string): TerminateResponse { if (Platform.isWindows) { try { - let options: any = { + const options: any = { stdio: ['pipe', 'pipe', 'ignore'] }; if (cwd) { @@ -54,8 +54,8 @@ export function terminateProcess(process: cp.ChildProcess, cwd?: string): Termin } } else if (Platform.isLinux || Platform.isMacintosh) { try { - let cmd = getPathFromAmdModule(require, 'vs/base/node/terminateProcess.sh'); - let result = cp.spawnSync(cmd, [process.pid.toString()]); + const cmd = getPathFromAmdModule(require, 'vs/base/node/terminateProcess.sh'); + const result = cp.spawnSync(cmd, [process.pid.toString()]); if (result.error) { return { success: false, error: result.error }; } @@ -113,7 +113,7 @@ export abstract class AbstractProcess { this.shell = arg3; this.options = arg4; } else { - let executable = arg1; + const executable = arg1; this.cmd = executable.command; this.shell = executable.isShellCommand; this.args = executable.args.slice(0); @@ -124,7 +124,7 @@ export abstract class AbstractProcess { this.terminateRequested = false; if (this.options.env) { - let newEnv: IStringDictionary = Object.create(null); + const newEnv: IStringDictionary = Object.create(null); Object.keys(process.env).forEach((key) => { newEnv[key] = process.env[key]!; }); @@ -137,7 +137,7 @@ export abstract class AbstractProcess { public getSanitizedCommand(): string { let result = this.cmd.toLowerCase(); - let index = result.lastIndexOf(path.sep); + const index = result.lastIndexOf(path.sep); if (index !== -1) { result = result.substring(index + 1); } @@ -154,7 +154,7 @@ export abstract class AbstractProcess { return this.useExec().then((useExec) => { let cc: ValueCallback; let ee: ErrorCallback; - let result = new Promise((c, e) => { + const result = new Promise((c, e) => { cc = c; ee = e; }); @@ -166,7 +166,7 @@ export abstract class AbstractProcess { } this.childProcess = cp.exec(cmd, this.options, (error, stdout, stderr) => { this.childProcess = null; - let err: any = error; + const err: any = error; // This is tricky since executing a command shell reports error back in case the executed command return an // error or the command didn't exist at all. So we can't blindly treat an error as a failed command. So we // always parse the output and report success unless the job got killed. @@ -178,11 +178,11 @@ export abstract class AbstractProcess { }); } else { let childProcess: cp.ChildProcess | null = null; - let closeHandler = (data: any) => { + const closeHandler = (data: any) => { this.childProcess = null; this.childProcessPromise = null; this.handleClose(data, cc, pp, ee); - let result: SuccessData = { + const result: SuccessData = { terminated: this.terminateRequested }; if (Types.isNumber(data)) { @@ -191,12 +191,12 @@ export abstract class AbstractProcess { cc(result); }; if (this.shell && Platform.isWindows) { - let options: any = Objects.deepClone(this.options); + const options: any = Objects.deepClone(this.options); options.windowsVerbatimArguments = true; options.detached = false; let quotedCommand: boolean = false; let quotedArg: boolean = false; - let commandLine: string[] = []; + const commandLine: string[] = []; let quoted = this.ensureQuotes(this.cmd); commandLine.push(quoted.value); quotedCommand = quoted.quoted; @@ -207,7 +207,7 @@ export abstract class AbstractProcess { quotedArg = quotedArg && quoted.quoted; }); } - let args: string[] = [ + const args: string[] = [ '/s', '/c', ]; @@ -287,7 +287,7 @@ export abstract class AbstractProcess { } return this.childProcessPromise.then((childProcess) => { this.terminateRequested = true; - let result = terminateProcess(childProcess, this.options.cwd); + const result = terminateProcess(childProcess, this.options.cwd); if (result.success) { this.childProcess = null; } @@ -302,7 +302,7 @@ export abstract class AbstractProcess { if (!this.shell || !Platform.isWindows) { return c(false); } - let cmdShell = cp.spawn(getWindowsShell(), ['/s', '/c']); + const cmdShell = cp.spawn(getWindowsShell(), ['/s', '/c']); cmdShell.on('error', (error: Error) => { return c(true); }); @@ -326,12 +326,12 @@ export class LineProcess extends AbstractProcess { protected handleExec(cc: ValueCallback, pp: ProgressCallback, error: Error, stdout: Buffer, stderr: Buffer) { [stdout, stderr].forEach((buffer: Buffer, index: number) => { - let lineDecoder = new LineDecoder(); - let lines = lineDecoder.write(buffer); + const lineDecoder = new LineDecoder(); + const lines = lineDecoder.write(buffer); lines.forEach((line) => { pp({ line: line, source: index === 0 ? Source.stdout : Source.stderr }); }); - let line = lineDecoder.end(); + const line = lineDecoder.end(); if (line) { pp({ line: line, source: index === 0 ? Source.stdout : Source.stderr }); } @@ -343,11 +343,11 @@ export class LineProcess extends AbstractProcess { this.stdoutLineDecoder = new LineDecoder(); this.stderrLineDecoder = new LineDecoder(); childProcess.stdout.on('data', (data: Buffer) => { - let lines = this.stdoutLineDecoder.write(data); + const lines = this.stdoutLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stdout })); }); childProcess.stderr.on('data', (data: Buffer) => { - let lines = this.stderrLineDecoder.write(data); + const lines = this.stderrLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stderr })); }); } @@ -380,7 +380,7 @@ export function createQueuedSender(childProcess: cp.ChildProcess): IQueuedSender return; } - let result = childProcess.send(msg, (error: Error) => { + const result = childProcess.send(msg, (error: Error) => { if (error) { console.error(error); // unlikely to happen, best we can do is log this error } @@ -412,7 +412,7 @@ export namespace win32 { if (cwd === undefined) { cwd = process.cwd(); } - let dir = path.dirname(command); + const dir = path.dirname(command); if (dir !== '.') { // We have a directory and the directory is relative (see above). Make the path absolute // to the current working directory. diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts index e42e9420809..8a0b2845c4f 100644 --- a/src/vs/base/node/ps.ts +++ b/src/vs/base/node/ps.ts @@ -151,7 +151,7 @@ export function listProcesses(rootPid: number): Promise { rootItem = processItems.get(rootPid); if (rootItem) { processItems.forEach(item => { - let parent = processItems.get(item.ppid); + const parent = processItems.get(item.ppid); if (parent) { if (!parent.children) { parent.children = []; @@ -186,7 +186,7 @@ export function listProcesses(rootPid: number): Promise { const lines = stdout.toString().split('\n'); for (const line of lines) { - let matches = PID_CMD.exec(line.trim()); + const matches = PID_CMD.exec(line.trim()); if (matches && matches.length === 6) { addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4])); } diff --git a/src/vs/base/node/request.ts b/src/vs/base/node/request.ts index 0d8d7434f66..ea24cdb7589 100644 --- a/src/vs/base/node/request.ts +++ b/src/vs/base/node/request.ts @@ -152,7 +152,7 @@ export function asText(context: IRequestContext): Promise { return c(null); } - let buffer: string[] = []; + const buffer: string[] = []; context.stream.on('data', (d: string) => buffer.push(d)); context.stream.on('end', () => c(buffer.join(''))); context.stream.on('error', e); diff --git a/src/vs/base/node/stats.ts b/src/vs/base/node/stats.ts index 4b89e868fe1..1c3598a5d30 100644 --- a/src/vs/base/node/stats.ts +++ b/src/vs/base/node/stats.ts @@ -21,15 +21,15 @@ export interface WorkspaceStats { } function asSortedItems(map: Map): WorkspaceStatItem[] { - let a: WorkspaceStatItem[] = []; + const a: WorkspaceStatItem[] = []; map.forEach((value, index) => a.push({ name: index, count: value })); return a.sort((a, b) => b.count - a.count); } export function collectLaunchConfigs(folder: string): Promise { - let launchConfigs = new Map(); + const launchConfigs = new Map(); - let launchConfig = join(folder, '.vscode', 'launch.json'); + const launchConfig = join(folder, '.vscode', 'launch.json'); return new Promise((resolve, reject) => { exists(launchConfig, (doesExist) => { if (doesExist) { @@ -87,8 +87,8 @@ export async function collectWorkspaceStats(folder: string, filter: string[]): P { 'tag': 'cmake', 'pattern': /^.+\.cmake$/i } ]; - let fileTypes = new Map(); - let configFiles = new Map(); + const fileTypes = new Map(); + const configFiles = new Map(); const MAX_FILES = 20000; @@ -149,7 +149,7 @@ export async function collectWorkspaceStats(folder: string, filter: string[]): P }); } - let addFileType = (fileType: string) => { + const addFileType = (fileType: string) => { if (fileTypes.has(fileType)) { fileTypes.set(fileType, fileTypes.get(fileType)! + 1); } @@ -158,7 +158,7 @@ export async function collectWorkspaceStats(folder: string, filter: string[]): P } }; - let addConfigFiles = (fileName: string) => { + const addConfigFiles = (fileName: string) => { for (const each of configFilePatterns) { if (each.pattern.test(fileName)) { if (configFiles.has(each.tag)) { @@ -170,9 +170,9 @@ export async function collectWorkspaceStats(folder: string, filter: string[]): P } }; - let acceptFile = (name: string) => { + const acceptFile = (name: string) => { if (name.lastIndexOf('.') >= 0) { - let suffix: string | undefined = name.split('.').pop(); + const suffix: string | undefined = name.split('.').pop(); if (suffix) { addFileType(suffix); } @@ -180,13 +180,13 @@ export async function collectWorkspaceStats(folder: string, filter: string[]): P addConfigFiles(name); }; - let token: { count: number, maxReached: boolean } = { count: 0, maxReached: false }; + const token: { count: number, maxReached: boolean } = { count: 0, maxReached: false }; return new Promise((resolve, reject) => { walk(folder, filter, token, async (files) => { files.forEach(acceptFile); - let launchConfigs = await collectLaunchConfigs(folder); + const launchConfigs = await collectLaunchConfigs(folder); resolve({ configFiles: asSortedItems(configFiles), diff --git a/src/vs/base/node/stream.ts b/src/vs/base/node/stream.ts index 845afdab8e9..1c8d7e73ede 100644 --- a/src/vs/base/node/stream.ts +++ b/src/vs/base/node/stream.ts @@ -92,7 +92,7 @@ export function readToMatchingString(file: string, matchingString: string, chunk }); } - let buffer = Buffer.allocUnsafe(maximumBytesToRead); + const buffer = Buffer.allocUnsafe(maximumBytesToRead); let offset = 0; function readChunk(): void { diff --git a/src/vs/base/node/zip.ts b/src/vs/base/node/zip.ts index cb9fbfbf25e..e2221f1b243 100644 --- a/src/vs/base/node/zip.ts +++ b/src/vs/base/node/zip.ts @@ -49,7 +49,7 @@ export class ExtractError extends Error { } function modeFromEntry(entry: Entry) { - let attr = entry.externalFileAttributes >> 16 || 33188; + const attr = entry.externalFileAttributes >> 16 || 33188; return [448 /* S_IRWXU */, 56 /* S_IRWXG */, 7 /* S_IRWXO */] .map(mask => attr & mask) From 38c3f4bedefce282a51f669c2468d781f5b8529b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 17:07:14 -0800 Subject: [PATCH 134/172] Use config file diagnostics provided by TS Server Fixes #69880 --- .../src/typeScriptServiceClientHost.ts | 45 +++---------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts index 890a30fcc06..68e3dd484ab 100644 --- a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts +++ b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts @@ -217,47 +217,16 @@ export default class TypeScriptServiceClientHost extends Disposable { return; } - (this.findLanguage(this.client.toResource(body.configFile))).then(language => { + this.findLanguage(this.client.toResource(body.configFile)).then(language => { if (!language) { return; } - if (body.diagnostics.length === 0) { - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), []); - } else if (body.diagnostics.length >= 1) { - vscode.workspace.openTextDocument(vscode.Uri.file(body.configFile)).then((document) => { - let curly: [number, number, number] | undefined = undefined; - let nonCurly: [number, number, number] | undefined = undefined; - let diagnostic: vscode.Diagnostic; - for (let index = 0; index < document.lineCount; index++) { - const line = document.lineAt(index); - const text = line.text; - const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex; - if (firstNonWhitespaceCharacterIndex < text.length) { - if (text.charAt(firstNonWhitespaceCharacterIndex) === '{') { - curly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + 1]; - break; - } else { - const matches = /\s*([^\s]*)(?:\s*|$)/.exec(text.substr(firstNonWhitespaceCharacterIndex)); - if (matches && matches.length >= 1) { - nonCurly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + matches[1].length]; - } - } - } - } - const match = curly || nonCurly; - if (match) { - diagnostic = new vscode.Diagnostic(new vscode.Range(match[0], match[1], match[0], match[2]), body.diagnostics[0].text); - } else { - diagnostic = new vscode.Diagnostic(new vscode.Range(0, 0, 0, 0), body.diagnostics[0].text); - } - if (diagnostic) { - diagnostic.source = language.diagnosticSource; - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [diagnostic]); - } - }, _error => { - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [new vscode.Diagnostic(new vscode.Range(0, 0, 0, 0), body.diagnostics[0].text)]); - }); - } + + language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), body.diagnostics.map(tsDiag => { + const diagnostic = new vscode.Diagnostic(typeConverters.Range.fromTextSpan(tsDiag), body.diagnostics[0].text); + diagnostic.source = language.diagnosticSource; + return diagnostic; + })); }); } From 1adb3256ea092a0d47d1d02439f3fa0678025039 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Tue, 5 Mar 2019 17:26:43 -0800 Subject: [PATCH 135/172] Show a quickpick for changing display language (#69570) --- .../browser/localizationsActions.ts | 91 +++++++++++++------ 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts index 3ee31d1c836..bbd759cb98d 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts @@ -5,50 +5,83 @@ import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; -import { IFileService } from 'vs/platform/files/common/files'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IEditor } from 'vs/workbench/common/editor'; import { join } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; +import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; +import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { INotificationService } from 'vs/platform/notification/common/notification'; import { language } from 'vs/base/common/platform'; -import { ILabelService } from 'vs/platform/label/common/label'; +import { firstIndex } from 'vs/base/common/arrays'; +import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export class ConfigureLocaleAction extends Action { public static readonly ID = 'workbench.action.configureLocale'; public static readonly LABEL = localize('configureLocale', "Configure Display Language"); - private static DEFAULT_CONTENT: string = [ - '{', - `\t// ${localize('displayLanguage', 'Defines VS Code\'s display language.')}`, - `\t// ${localize('doc', 'See {0} for a list of supported languages.', 'https://go.microsoft.com/fwlink/?LinkId=761051')}`, - `\t`, - `\t"locale":"${language}" // ${localize('restart', 'Changes will not take effect until VS Code has been restarted.')}`, - '}' - ].join('\n'); - constructor(id: string, label: string, - @IFileService private readonly fileService: IFileService, @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IEditorService private readonly editorService: IEditorService, - @ILabelService private readonly labelService: ILabelService + @ILocalizationsService private readonly localizationService: ILocalizationsService, + @IQuickInputService private readonly quickInputService: IQuickInputService, + @IJSONEditingService private readonly jsonEditingService: IJSONEditingService, + @IWindowsService private readonly windowsService: IWindowsService, + @INotificationService private readonly notificationService: INotificationService, + @IViewletService private readonly viewletService: IViewletService, + @IDialogService private readonly dialogService: IDialogService ) { super(id, label); } - public run(event?: any): Promise { - const file = URI.file(join(this.environmentService.appSettingsHome, 'locale.json')); - return this.fileService.resolveFile(file).then(undefined, (error) => { - return this.fileService.createFile(file, ConfigureLocaleAction.DEFAULT_CONTENT); - }).then((stat): Promise | null => { - if (!stat) { - return null; + private async getLanguageOptions(): Promise { + // Contributed languages are those installed via extension packs, so does not include English + const availableLanguages = ['en', ...await this.localizationService.getLanguageIds(LanguageType.Contributed)]; + availableLanguages.sort(); + + return availableLanguages + .map(language => { return { label: language }; }) + .concat({ label: localize('installAdditionalLanguages', "Install additional languages...") }); + } + + public async run(event?: any): Promise { + const languageOptions = await this.getLanguageOptions(); + const currentLanguageIndex = firstIndex(languageOptions, l => l.label === language); + + try { + const selectedLanguage = await this.quickInputService.pick(languageOptions, + { + canPickMany: false, + placeHolder: localize('chooseDisplayLanguage', "Select Display Language"), + activeItem: languageOptions[currentLanguageIndex] + }); + + if (selectedLanguage === languageOptions[languageOptions.length - 1]) { + return this.viewletService.openViewlet(EXTENSIONS_VIEWLET_ID, true) + .then((viewlet: IExtensionsViewlet) => { + viewlet.search('@category:"language packs"'); + viewlet.focus(); + }); } - return this.editorService.openEditor({ - resource: stat.resource - }); - }, (error) => { - throw new Error(localize('fail.createSettings', "Unable to create '{0}' ({1}).", this.labelService.getUriLabel(file, { relative: true }), error)); - }); + + if (selectedLanguage) { + const file = URI.file(join(this.environmentService.appSettingsHome, 'locale.json')); + await this.jsonEditingService.write(file, { 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."), + detail: localize('relaunchDisplayLanguageDetail', "Press the restart button to restart {0} and change the display language.", this.environmentService.appNameLong), + primaryButton: localize('restart', "&&Restart") + }); + + if (restart.confirmed) { + this.windowsService.relaunch({}); + } + } + } catch (e) { + this.notificationService.error(e); + } } } From 0710a009f8cf56a5f8ee6403f61c158a1df493bc Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 16:11:40 -0800 Subject: [PATCH 136/172] Fix #69875 --- src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts | 2 +- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostWorkspace.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index fe39eeef61a..c2b3d540575 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -119,7 +119,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- search --- - $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number, token: CancellationToken): Promise { const includeFolder = URI.revive(_includeFolder); const workspace = this._contextService.getWorkspace(); if (!workspace.folders.length) { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index e7cb2b72c07..53df36fbf27 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -527,7 +527,7 @@ export interface ExtHostUrlsShape { } export interface MainThreadWorkspaceShape extends IDisposable { - $startFileSearch(includePattern: string | undefined, includeFolder: URI | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise; + $startFileSearch(includePattern: string | undefined, includeFolder: URI | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number, token: CancellationToken): Promise; $startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise; $checkExists(includes: string[], token: CancellationToken): Promise; $saveAll(includeUntitled?: boolean): Promise; diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index 785ad829cba..bcd01710615 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -405,7 +405,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac } } - let excludePatternOrDisregardExcludes: string | false = false; + let excludePatternOrDisregardExcludes: string | false | undefined = undefined; if (exclude === null) { excludePatternOrDisregardExcludes = false; } else if (exclude) { From 92629f3f5f4c662a26cc193b5208c3ff3a335243 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 5 Mar 2019 19:17:21 -0800 Subject: [PATCH 137/172] findFiles tests --- .../src/singlefolder-tests/workspace.test.ts | 7 + .../services/search/common/search.ts | 3 - .../api/extHostWorkspace.test.ts | 123 ++++++++++++++++-- .../api/mainThreadWorkspace.test.ts | 101 ++++++++++++++ 4 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index 2f46c461b3f..a1e85fc4daf 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -494,6 +494,13 @@ suite('workspace-namespace', () => { }); }); + test('findFiles - exclude', () => { + return vscode.workspace.findFiles('**/*.png').then((res) => { + assert.equal(res.length, 2); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + }); + }); + test('findFiles, exclude', () => { return vscode.workspace.findFiles('**/*.png', '**/sub/**').then((res) => { assert.equal(res.length, 1); diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index 16f1f7af4d9..a109834cc1a 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -71,9 +71,6 @@ export interface IFileQueryProps extends ICommonQueryPr type: QueryType.File; filePattern?: string; - // TODO: Remove this! - disregardExcludeSettings?: boolean; - /** * If true no results will be returned. Instead `limitHit` will indicate if at least one result exists or not. * Currently does not work with queries including a 'siblings clause'. diff --git a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts index 40de7dbe2b3..5974b4713f5 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts @@ -4,16 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { URI } from 'vs/base/common/uri'; -import { basename } from 'vs/base/common/path'; -import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; -import { TestRPCProtocol } from './testRPCProtocol'; -import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace'; -import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { NullLogService, ILogService } from 'vs/platform/log/common/log'; -import { IMainContext, IWorkspaceData } from 'vs/workbench/api/node/extHost.protocol'; +import { CancellationToken } from 'vs/base/common/cancellation'; import { Counter } from 'vs/base/common/numbers'; +import { basename } from 'vs/base/common/path'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { ILogService, NullLogService } from 'vs/platform/log/common/log'; +import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace'; +import { MainThreadWorkspace } from 'vs/workbench/api/electron-browser/mainThreadWorkspace'; +import { IMainContext, IWorkspaceData, MainContext } from 'vs/workbench/api/node/extHost.protocol'; +import { RelativePattern } from 'vs/workbench/api/node/extHostTypes'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; +import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +import { mock } from 'vs/workbench/test/electron-browser/api/mock'; +import { TestRPCProtocol } from './testRPCProtocol'; function createExtHostWorkspace(mainContext: IMainContext, data: IWorkspaceData, logService: ILogService, requestIdProvider: Counter): ExtHostWorkspace { const result = new ExtHostWorkspace(mainContext, logService, requestIdProvider); @@ -563,4 +567,107 @@ suite('ExtHostWorkspace', function () { function asUpdateWorkspaceFolderData(uri: URI, name?: string): { uri: URI, name?: string } { return { uri, name }; } + + test('findFiles - string include', () => { + const root = '/project/foo'; + const rpcProtocol = new TestRPCProtocol(); + + let mainThreadCalled = false; + rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock() { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + mainThreadCalled = true; + assert.equal(includePattern, 'foo'); + assert.equal(_includeFolder, undefined); + assert.equal(excludePatternOrDisregardExcludes, undefined); + assert.equal(maxResults, 10); + return Promise.resolve(undefined); + } + }); + + const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + return ws.findFiles('foo', undefined!, 10, new ExtensionIdentifier('test')).then(() => { + assert(mainThreadCalled, 'mainThreadCalled'); + }); + }); + + test('findFiles - RelativePattern include', () => { + const root = '/project/foo'; + const rpcProtocol = new TestRPCProtocol(); + + let mainThreadCalled = false; + rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock() { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + mainThreadCalled = true; + assert.equal(includePattern, 'glob/**'); + assert.deepEqual(_includeFolder, URI.file('/other/folder').toJSON()); + assert.equal(excludePatternOrDisregardExcludes, undefined); + return Promise.resolve(undefined); + } + }); + + const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), undefined!, 10, new ExtensionIdentifier('test')).then(() => { + assert(mainThreadCalled, 'mainThreadCalled'); + }); + }); + + test('findFiles - no excludes', () => { + const root = '/project/foo'; + const rpcProtocol = new TestRPCProtocol(); + + let mainThreadCalled = false; + rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock() { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + mainThreadCalled = true; + assert.equal(includePattern, 'glob/**'); + assert.deepEqual(_includeFolder, URI.file('/other/folder').toJSON()); + assert.equal(excludePatternOrDisregardExcludes, false); + return Promise.resolve(undefined); + } + }); + + const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), null!, 10, new ExtensionIdentifier('test')).then(() => { + assert(mainThreadCalled, 'mainThreadCalled'); + }); + }); + + test('findFiles - with cancelled token', () => { + const root = '/project/foo'; + const rpcProtocol = new TestRPCProtocol(); + + let mainThreadCalled = false; + rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock() { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + mainThreadCalled = true; + return Promise.resolve(undefined); + } + }); + + const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + + const token = CancellationToken.Cancelled; + return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), null!, 10, new ExtensionIdentifier('test'), token).then(() => { + assert(!mainThreadCalled, '!mainThreadCalled'); + }); + }); + + test('findFiles - RelativePattern exclude', () => { + const root = '/project/foo'; + const rpcProtocol = new TestRPCProtocol(); + + let mainThreadCalled = false; + rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock() { + $startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise { + mainThreadCalled = true; + assert(excludePatternOrDisregardExcludes, 'glob/**'); // Note that the base portion is ignored, see #52651 + return Promise.resolve(undefined); + } + }); + + const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService(), new Counter()); + return ws.findFiles('', new RelativePattern(root, 'glob/**'), 10, new ExtensionIdentifier('test')).then(() => { + assert(mainThreadCalled, 'mainThreadCalled'); + }); + }); }); diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts new file mode 100644 index 00000000000..fc2e5cd50b5 --- /dev/null +++ b/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts @@ -0,0 +1,101 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { ISearchService, IFileQuery } from 'vs/workbench/services/search/common/search'; +import { MainThreadWorkspace } from 'vs/workbench/api/electron-browser/mainThreadWorkspace'; +import * as assert from 'assert'; +import { SingleProxyRPCProtocol } from 'vs/workbench/test/electron-browser/api/testRPCProtocol'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; + +suite('MainThreadWorkspace', () => { + + let configService: TestConfigurationService; + let instantiationService: TestInstantiationService; + + setup(() => { + instantiationService = workbenchInstantiationService() as TestInstantiationService; + + configService = instantiationService.get(IConfigurationService) as TestConfigurationService; + configService.setUserConfiguration('search', {}); + }); + + test('simple', () => { + instantiationService.stub(ISearchService, { + fileSearch(query: IFileQuery) { + assert.equal(query.folderQueries.length, 1); + assert.equal(query.folderQueries[0].disregardIgnoreFiles, true); + + assert.deepEqual(query.includePattern, { 'foo': true }); + assert.equal(query.maxResults, 10); + + return Promise.resolve({ results: [] }); + } + }); + + const mtw: MainThreadWorkspace = instantiationService.createInstance(MainThreadWorkspace, SingleProxyRPCProtocol({ $initializeWorkspace: () => { } })); + return mtw.$startFileSearch('foo', undefined, undefined, 10, new CancellationTokenSource().token); + }); + + test('exclude defaults', () => { + configService.setUserConfiguration('search', { + 'exclude': { 'searchExclude': true } + }); + configService.setUserConfiguration('files', { + 'exclude': { 'filesExclude': true } + }); + + instantiationService.stub(ISearchService, { + fileSearch(query: IFileQuery) { + assert.equal(query.folderQueries.length, 1); + assert.equal(query.folderQueries[0].disregardIgnoreFiles, true); + assert.deepEqual(query.folderQueries[0].excludePattern, { 'filesExclude': true }); + + return Promise.resolve({ results: [] }); + } + }); + + const mtw: MainThreadWorkspace = instantiationService.createInstance(MainThreadWorkspace, SingleProxyRPCProtocol({ $initializeWorkspace: () => { } })); + return mtw.$startFileSearch('', undefined, undefined, 10, new CancellationTokenSource().token); + }); + + test('disregard excludes', () => { + configService.setUserConfiguration('search', { + 'exclude': { 'searchExclude': true } + }); + configService.setUserConfiguration('files', { + 'exclude': { 'filesExclude': true } + }); + + instantiationService.stub(ISearchService, { + fileSearch(query: IFileQuery) { + assert.equal(query.folderQueries[0].excludePattern, undefined); + assert.deepEqual(query.excludePattern, undefined); + + return Promise.resolve({ results: [] }); + } + }); + + const mtw: MainThreadWorkspace = instantiationService.createInstance(MainThreadWorkspace, SingleProxyRPCProtocol({ $initializeWorkspace: () => { } })); + return mtw.$startFileSearch('', undefined, false, 10, new CancellationTokenSource().token); + }); + + test('exclude string', () => { + instantiationService.stub(ISearchService, { + fileSearch(query: IFileQuery) { + assert.equal(query.folderQueries[0].excludePattern, undefined); + assert.deepEqual(query.excludePattern, { 'exclude/**': true }); + + return Promise.resolve({ results: [] }); + } + }); + + const mtw: MainThreadWorkspace = instantiationService.createInstance(MainThreadWorkspace, SingleProxyRPCProtocol({ $initializeWorkspace: () => { } })); + return mtw.$startFileSearch('', undefined, 'exclude/**', 10, new CancellationTokenSource().token); + }); +}); From 556bfbeee6ec5126e4a7d84581ef4f14afb043b0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 09:48:15 +0100 Subject: [PATCH 138/172] fix #43270 --- .../contrib/snippet/snippetController2.ts | 21 +++++++++-- .../editor/contrib/snippet/snippetSession.ts | 10 +++--- .../snippet/test/snippetController2.test.ts | 36 ++++++++++++++----- .../snippet/test/snippetSession.test.ts | 2 +- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index 3f87729b6ab..eadc88a2545 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -19,6 +19,7 @@ import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from ' import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ILogService } from 'vs/platform/log/common/log'; import { SnippetSession } from './snippetSession'; +import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState'; export class SnippetController2 implements IEditorContribution { @@ -113,10 +114,26 @@ export class SnippetController2 implements IEditorContribution { this._updateState(); + // we listen on model and selection changes. usually + // both events come in together and this is to prevent + // that we don't call _updateState twice. + let state: EditorState; + let dedupedUpdateState = () => { + if (!state || !state.validate(this._editor)) { + this._updateState(); + state = new EditorState(this._editor, CodeEditorStateFlag.Selection | CodeEditorStateFlag.Value); + } + }; this._snippetListener = [ - this._editor.onDidChangeModelContent(e => e.isFlush && this.cancel()), + this._editor.onDidChangeModelContent(e => { + if (e.isFlush) { + this.cancel(); + } else { + setTimeout(dedupedUpdateState, 0); + } + }), + this._editor.onDidChangeCursorSelection(dedupedUpdateState), this._editor.onDidChangeModel(() => this.cancel()), - this._editor.onDidChangeCursorSelection(() => this._updateState()) ]; } diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts index 53cb0ed3c15..31cfa72a41c 100644 --- a/src/vs/editor/contrib/snippet/snippetSession.ts +++ b/src/vs/editor/contrib/snippet/snippetSession.ts @@ -197,10 +197,6 @@ export class OneSnippet { let ranges: Range[] | undefined; for (const placeholder of placeholdersWithEqualIndex) { - if (placeholder.isFinalTabstop) { - // ignore those - break; - } if (!ranges) { ranges = []; @@ -574,6 +570,12 @@ export class SnippetSession { return false; } + if (allPossibleSelections.has(0)) { + // selection overlaps with a final tab stop which means + // we done + return false; + } + // add selections from 'this' snippet so that we know all // selections for this placeholder allPossibleSelections.forEach((array, index) => { diff --git a/src/vs/editor/contrib/snippet/test/snippetController2.test.ts b/src/vs/editor/contrib/snippet/test/snippetController2.test.ts index 95395786fd0..bfb0cf61727 100644 --- a/src/vs/editor/contrib/snippet/test/snippetController2.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetController2.test.ts @@ -11,6 +11,7 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { NullLogService } from 'vs/platform/log/common/log'; import { Handler } from 'vs/editor/common/editorCommon'; +import { timeout } from 'vs/base/common/async'; suite('SnippetController2', function () { @@ -133,11 +134,11 @@ suite('SnippetController2', function () { assertSelections(editor, new Selection(1, 1, 1, 7), new Selection(2, 5, 2, 11)); editor.trigger('test', 'cut', {}); - assertContextKeys(contextKeys, true, false, true); + assertContextKeys(contextKeys, false, false, false); assertSelections(editor, new Selection(1, 1, 1, 1), new Selection(2, 5, 2, 5)); editor.trigger('test', 'type', { text: 'abc' }); - assertContextKeys(contextKeys, true, false, true); + assertContextKeys(contextKeys, false, false, false); ctrl.next(); assertContextKeys(contextKeys, false, false, false); @@ -159,9 +160,9 @@ suite('SnippetController2', function () { assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8)); assertContextKeys(contextKeys, true, false, true); - ctrl.next(); - assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); - assertContextKeys(contextKeys, true, true, true); + // ctrl.next(); + // assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); + // assertContextKeys(contextKeys, true, true, true); ctrl.next(); assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); @@ -176,10 +177,10 @@ suite('SnippetController2', function () { ctrl.insert('farboo'); assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); - assertContextKeys(contextKeys, true, false, true); + // assertContextKeys(contextKeys, true, false, true); - ctrl.next(); - assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); + // ctrl.next(); + // assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); assertContextKeys(contextKeys, false, false, false); }); @@ -401,4 +402,23 @@ suite('SnippetController2', function () { assertContextKeys(contextKeys, false, false, false); assertSelections(editor, new Selection(1, 22, 1, 22)); }); + + test('A little confusing visual effect of highlighting for snippet tabstop #43270', async function () { + const ctrl = new SnippetController2(editor, logService, contextKeys); + model.setValue(''); + editor.setSelection(new Selection(1, 1, 1, 1)); + + ctrl.insert('background-color: ${1:fff};$0'); + assertSelections(editor, new Selection(1, 19, 1, 22)); + + editor.setSelection(new Selection(1, 22, 1, 22)); + assertContextKeys(contextKeys, true, false, true); + editor.trigger('', 'deleteRight', null); + + assert.equal(model.getValue(), 'background-color: fff'); + + await timeout(0); // this depends on re-scheduling of events... + + assertContextKeys(contextKeys, false, false, false); + }); }); diff --git a/src/vs/editor/contrib/snippet/test/snippetSession.test.ts b/src/vs/editor/contrib/snippet/test/snippetSession.test.ts index 0d2ec457b50..924f9a6d230 100644 --- a/src/vs/editor/contrib/snippet/test/snippetSession.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetSession.test.ts @@ -331,7 +331,7 @@ suite('SnippetSession', function () { // reset selection to placeholder session.next(); - assert.equal(session.isSelectionWithinPlaceholders(), true); + assert.equal(session.isSelectionWithinPlaceholders(), false); assert.equal(session.isAtLastPlaceholder, true); assertSelections(editor, new Selection(1, 13, 1, 13), new Selection(2, 17, 2, 17)); }); From 0b9e2a1c8a6e041aabf813e73a3876a2c667ac48 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 6 Mar 2019 09:57:44 +0100 Subject: [PATCH 139/172] If the code editor is readonly still alow bulk edits to be applied --- src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index 5137f89c2c5..f532d978e35 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -410,6 +410,10 @@ export class BulkEditService implements IBulkEditService { } } + if (codeEditor && codeEditor.getConfiguration().readOnly) { + // If the code editor is readonly still allow bulk edits to be applied #68549 + codeEditor = undefined; + } const bulkEdit = new BulkEdit(codeEditor, options.progress, this._logService, this._textModelService, this._fileService, this._textFileService, this._labelService, this._configurationService); bulkEdit.add(edits); From ec878903e941e09af53936262470ce9de6370826 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 6 Mar 2019 10:18:15 +0100 Subject: [PATCH 140/172] Fix #69849 --- .../editor/contrib/hover/modesContentHover.ts | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index bf6bab44890..671da624c7b 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -24,7 +24,7 @@ import { ContentHoverWidget } from 'vs/editor/contrib/hover/hoverWidgets'; import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; -import { IMarker, IMarkerData } from 'vs/platform/markers/common/markers'; +import { IMarker, IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { basename } from 'vs/base/common/resources'; import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -474,7 +474,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget { if (markerMessages.length) { markerMessages.forEach(msg => fragment.appendChild(this.renderMarkerHover(msg))); - fragment.appendChild(this.renderMarkerStatusbar(markerMessages[0])); + const markerHoverForStatusbar = markerMessages.length === 1 ? markerMessages[0] : markerMessages.sort((a, b) => MarkerSeverity.compare(a.marker.severity, b.marker.severity))[0]; + fragment.appendChild(this.renderMarkerStatusbar(markerHoverForStatusbar)); } // show @@ -550,15 +551,17 @@ export class ModesContentHoverWidget extends ContentHoverWidget { }); } })); - disposables.push(this.renderAction(actionsElement, { - label: nls.localize('peek problem', "Peek Problem"), - commandId: NextMarkerAction.ID, - run: () => { - this.hide(); - MarkerController.get(this._editor).show(markerHover.marker); - this._editor.focus(); - } - })); + if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) { + disposables.push(this.renderAction(actionsElement, { + label: nls.localize('peek problem', "Peek Problem"), + commandId: NextMarkerAction.ID, + run: () => { + this.hide(); + MarkerController.get(this._editor).show(markerHover.marker); + this._editor.focus(); + } + })); + } this.renderDisposable = combinedDisposable(disposables); return hoverElement; } From c4bed467841821c894f5b6da1fdac7e33ef7989c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Mar 2019 10:14:38 +0100 Subject: [PATCH 141/172] Add a download util that uses a separate process --- build/download/download.js | 91 ++++++++++++++++++++++++++++++ build/download/download.ts | 111 +++++++++++++++++++++++++++++++++++++ build/gulpfile.hygiene.js | 2 +- build/lib/util.js | 37 +++++++++++++ build/lib/util.ts | 38 +++++++++++++ 5 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 build/download/download.js create mode 100644 build/download/download.ts diff --git a/build/download/download.js b/build/download/download.js new file mode 100644 index 00000000000..c70bae336a6 --- /dev/null +++ b/build/download/download.js @@ -0,0 +1,91 @@ +"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 https = require("https"); +const fs = require("fs"); +const path = require("path"); +const cp = require("child_process"); +function ensureDir(filepath) { + if (!fs.existsSync(filepath)) { + ensureDir(path.dirname(filepath)); + fs.mkdirSync(filepath); + } +} +function download(options, destination) { + ensureDir(path.dirname(destination)); + return new Promise((c, e) => { + const fd = fs.openSync(destination, 'w'); + const req = https.get(options, (res) => { + res.on('data', (chunk) => { + fs.writeSync(fd, chunk); + }); + res.on('end', () => { + fs.closeSync(fd); + c(); + }); + }); + req.on('error', (reqErr) => { + console.error(`request to ${options.host}${options.path} failed.`); + console.error(reqErr); + e(reqErr); + }); + }); +} +const MARKER_ARGUMENT = `_download_fork_`; +function base64encode(str) { + return Buffer.from(str, 'utf8').toString('base64'); +} +function base64decode(str) { + return Buffer.from(str, 'base64').toString('utf8'); +} +function downloadInExternalProcess(options) { + const url = `https://${options.requestOptions.host}${options.requestOptions.path}`; + console.log(`Downloading ${url}...`); + return new Promise((c, e) => { + const child = cp.fork(__filename, [MARKER_ARGUMENT, base64encode(JSON.stringify(options))], { + stdio: ['pipe', 'pipe', 'pipe', 'ipc'] + }); + let stderr = []; + child.stderr.on('data', (chunk) => { + stderr.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk); + }); + child.on('exit', (code) => { + if (code === 0) { + // normal termination + console.log(`Finished downloading ${url}.`); + c(); + } + else { + // abnormal termination + console.error(Buffer.concat(stderr).toString()); + e(new Error(`Download of ${url} failed.`)); + } + }); + }); +} +exports.downloadInExternalProcess = downloadInExternalProcess; +function _downloadInExternalProcess() { + let options; + try { + options = JSON.parse(base64decode(process.argv[3])); + } + catch (err) { + console.error(`Cannot read arguments`); + console.error(err); + process.exit(-1); + return; + } + download(options.requestOptions, options.destinationPath).then(() => { + process.exit(0); + }, (err) => { + console.error(err); + process.exit(-2); + }); +} +if (process.argv.length >= 4 && process.argv[2] === MARKER_ARGUMENT) { + // running as forked download script + _downloadInExternalProcess(); +} diff --git a/build/download/download.ts b/build/download/download.ts new file mode 100644 index 00000000000..01ac8864d0b --- /dev/null +++ b/build/download/download.ts @@ -0,0 +1,111 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as https from 'https'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as cp from 'child_process'; + +function ensureDir(filepath: string) { + if (!fs.existsSync(filepath)) { + ensureDir(path.dirname(filepath)); + fs.mkdirSync(filepath); + } +} + +function download(options: https.RequestOptions, destination: string): Promise { + ensureDir(path.dirname(destination)); + + return new Promise((c, e) => { + const fd = fs.openSync(destination, 'w'); + const req = https.get(options, (res) => { + res.on('data', (chunk) => { + fs.writeSync(fd, chunk); + }); + res.on('end', () => { + fs.closeSync(fd); + c(); + }); + }); + req.on('error', (reqErr) => { + console.error(`request to ${options.host}${options.path} failed.`); + console.error(reqErr); + e(reqErr); + }); + }); +} + +const MARKER_ARGUMENT = `_download_fork_`; + +function base64encode(str: string): string { + return Buffer.from(str, 'utf8').toString('base64'); +} + +function base64decode(str: string): string { + return Buffer.from(str, 'base64').toString('utf8'); +} + +export interface IDownloadRequestOptions { + host: string; + path: string; +} + +export interface IDownloadOptions { + requestOptions: IDownloadRequestOptions; + destinationPath: string; +} + +export function downloadInExternalProcess(options: IDownloadOptions): Promise { + const url = `https://${options.requestOptions.host}${options.requestOptions.path}`; + console.log(`Downloading ${url}...`); + return new Promise((c, e) => { + const child = cp.fork( + __filename, + [MARKER_ARGUMENT, base64encode(JSON.stringify(options))], + { + stdio: ['pipe', 'pipe', 'pipe', 'ipc'] + } + ); + let stderr: Buffer[] = []; + child.stderr.on('data', (chunk) => { + stderr.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk); + }); + child.on('exit', (code) => { + if (code === 0) { + // normal termination + console.log(`Finished downloading ${url}.`); + c(); + } else { + // abnormal termination + console.error(Buffer.concat(stderr).toString()); + e(new Error(`Download of ${url} failed.`)); + } + }); + }); +} + +function _downloadInExternalProcess() { + let options: IDownloadOptions; + try { + options = JSON.parse(base64decode(process.argv[3])); + } catch (err) { + console.error(`Cannot read arguments`); + console.error(err); + process.exit(-1); + return; + } + + download(options.requestOptions, options.destinationPath).then(() => { + process.exit(0); + }, (err) => { + console.error(err); + process.exit(-2); + }); +} + +if (process.argv.length >= 4 && process.argv[2] === MARKER_ARGUMENT) { + // running as forked download script + _downloadInExternalProcess(); +} diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 187968a95bc..2525e625e43 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -81,7 +81,7 @@ const indentationFilter = [ '!src/typings/**/*.d.ts', '!extensions/**/*.d.ts', '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns}', - '!build/{lib,tslintRules}/**/*.js', + '!build/{lib,tslintRules,download}/**/*.js', '!build/**/*.sh', '!build/azure-pipelines/**/*.js', '!build/azure-pipelines/**/*.config', diff --git a/build/lib/util.js b/build/lib/util.js index 17edc75f65f..34ee13695fd 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -14,6 +14,8 @@ const fs = require("fs"); const _rimraf = require("rimraf"); const git = require("./git"); const VinylFile = require("vinyl"); +const download_1 = require("../download/download"); +const REPO_ROOT = path.join(__dirname, '../../'); const NoCancellationToken = { isCancellationRequested: () => false }; function incremental(streamProvider, initial, supportsCancellation) { const input = es.through(); @@ -221,3 +223,38 @@ function versionStringToNumber(versionStr) { return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); } exports.versionStringToNumber = versionStringToNumber; +function download(requestOptions) { + const result = es.through(); + const filename = path.join(REPO_ROOT, `.build/tmp-${Date.now()}-${path.posix.basename(requestOptions.path)}`); + const opts = { + requestOptions: requestOptions, + destinationPath: filename + }; + download_1.downloadInExternalProcess(opts).then(() => { + fs.stat(filename, (err, stat) => { + if (err) { + result.emit('error', err); + return; + } + fs.readFile(filename, (err, data) => { + if (err) { + result.emit('error', err); + return; + } + fs.unlink(filename, () => { + result.emit('data', new VinylFile({ + path: path.normalize(requestOptions.path), + stat: stat, + base: path.normalize(requestOptions.path), + contents: data + })); + result.emit('end'); + }); + }); + }); + }, (err) => { + result.emit('error', err); + }); + return result; +} +exports.download = download; diff --git a/build/lib/util.ts b/build/lib/util.ts index a773b2449da..44ac9d0dc74 100644 --- a/build/lib/util.ts +++ b/build/lib/util.ts @@ -17,6 +17,9 @@ import * as git from './git'; import * as VinylFile from 'vinyl'; import { ThroughStream } from 'through'; import * as sm from 'source-map'; +import { IDownloadOptions, downloadInExternalProcess, IDownloadRequestOptions } from '../download/download'; + +const REPO_ROOT = path.join(__dirname, '../../'); export interface ICancellationToken { isCancellationRequested(): boolean; @@ -280,3 +283,38 @@ export function versionStringToNumber(versionStr: string) { return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); } + +export function download(requestOptions: IDownloadRequestOptions): NodeJS.ReadWriteStream { + const result = es.through(); + const filename = path.join(REPO_ROOT, `.build/tmp-${Date.now()}-${path.posix.basename(requestOptions.path)}`); + const opts: IDownloadOptions = { + requestOptions: requestOptions, + destinationPath: filename + }; + downloadInExternalProcess(opts).then(() => { + fs.stat(filename, (err, stat) => { + if (err) { + result.emit('error', err); + return; + } + fs.readFile(filename, (err, data) => { + if (err) { + result.emit('error', err); + return; + } + fs.unlink(filename, () => { + result.emit('data', new VinylFile({ + path: path.normalize(requestOptions.path), + stat: stat, + base: path.normalize(requestOptions.path), + contents: data + })); + result.emit('end'); + }); + }); + }); + }, (err) => { + result.emit('error', err); + }); + return result; +} From caa10c9d053fd883d7b8d8fefd840dcf09d656ef Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Mar 2019 10:16:55 +0100 Subject: [PATCH 142/172] Simplify the Protocol implementation --- src/vs/base/parts/ipc/node/ipc.net.ts | 135 +++++++++++------- .../base/parts/ipc/test/node/ipc.net.test.ts | 35 ----- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index 08f2def654f..9cc68b10be5 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -10,7 +10,6 @@ import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { generateUuid } from 'vs/base/common/uuid'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { TimeoutTimer } from 'vs/base/common/async'; export function generateRandomPipeName(): string { const randomSuffix = generateUuid(); @@ -22,6 +21,80 @@ export function generateRandomPipeName(): string { } } +class ChunkStream { + + private _chunks: Buffer[]; + private _totalLength: number; + + public get byteLength() { + return this._totalLength; + } + + constructor() { + this._chunks = []; + this._totalLength = 0; + } + + public acceptChunk(buff: Buffer) { + this._chunks.push(buff); + this._totalLength += buff.byteLength; + } + + public readUInt32BE(): number { + let tmp = this.read(4); + return tmp.readUInt32BE(0); + } + + public read(byteCount: number): Buffer { + if (byteCount === 0) { + return Buffer.allocUnsafe(0); + } + + if (byteCount > this._totalLength) { + throw new Error(`Cannot read so many bytes!`); + } + + if (this._chunks[0].byteLength === byteCount) { + // super fast path, precisely first chunk must be returned + const result = this._chunks.shift()!; + this._totalLength -= byteCount; + return result; + } + + if (this._chunks[0].byteLength > byteCount) { + // fast path, the reading is entirely within the first chunk + const result = this._chunks[0].slice(0, byteCount); + this._chunks[0] = this._chunks[0].slice(byteCount); + this._totalLength -= byteCount; + return result; + } + + let result = Buffer.allocUnsafe(byteCount); + let resultOffset = 0; + while (byteCount > 0) { + const chunk = this._chunks[0]; + if (chunk.byteLength > byteCount) { + // this chunk will survive + this._chunks[0] = chunk.slice(byteCount); + + chunk.copy(result, resultOffset, 0, byteCount); + resultOffset += byteCount; + this._totalLength -= byteCount; + byteCount -= byteCount; + } else { + // this chunk will be entirely read + this._chunks.shift(); + + chunk.copy(result, resultOffset, 0, chunk.byteLength); + resultOffset += chunk.byteLength; + this._totalLength -= chunk.byteLength; + byteCount -= chunk.byteLength; + } + } + return result; + } +} + /** * A message has the following format: * @@ -35,9 +108,8 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { private static readonly _headerLen = 4; private _isDisposed: boolean; - private _chunks: Buffer[]; + private _incomingData: ChunkStream; - private _firstChunkTimer: TimeoutTimer; private _socketDataListener: (data: Buffer) => void; private _socketEndListener: () => void; private _socketCloseListener: () => void; @@ -48,11 +120,9 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { private _onClose = new Emitter(); readonly onClose: Event = this._onClose.event; - constructor(private _socket: Socket, firstDataChunk?: Buffer) { + constructor(private _socket: Socket) { this._isDisposed = false; - this._chunks = []; - - let totalLength = 0; + this._incomingData = new ChunkStream(); const state = { readHead: true, @@ -61,24 +131,15 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { const acceptChunk = (data: Buffer) => { - this._chunks.push(data); - totalLength += data.length; + this._incomingData.acceptChunk(data); - while (totalLength > 0) { + while (this._incomingData.byteLength > 0) { if (state.readHead) { - // expecting header -> read 5bytes for header - // information: `bodyIsJson` and `bodyLen` - if (totalLength >= Protocol._headerLen) { - const all = Buffer.concat(this._chunks); - - state.bodyLen = all.readUInt32BE(0); + // expecting header -> read header + if (this._incomingData.byteLength >= Protocol._headerLen) { + state.bodyLen = this._incomingData.readUInt32BE(); state.readHead = false; - - const rest = all.slice(Protocol._headerLen); - totalLength = rest.length; - this._chunks = [rest]; - } else { break; } @@ -87,15 +148,8 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { if (!state.readHead) { // expecting body -> read bodyLen-bytes for // the actual message or wait for more data - if (totalLength >= state.bodyLen) { - - const all = Buffer.concat(this._chunks); - const buffer = all.slice(0, state.bodyLen); - - // ensure the getBuffer returns a valid value if invoked from the event listeners - const rest = all.slice(state.bodyLen); - totalLength = rest.length; - this._chunks = [rest]; + if (this._incomingData.byteLength >= state.bodyLen) { + const buffer = this._incomingData.read(state.bodyLen); state.bodyLen = -1; state.readHead = true; @@ -113,28 +167,12 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { } }; - const acceptFirstDataChunk = () => { - if (firstDataChunk && firstDataChunk.length > 0) { - let tmp = firstDataChunk; - firstDataChunk = undefined; - acceptChunk(tmp); - } - }; - - // Make sure to always handle the firstDataChunk if no more `data` event comes in - this._firstChunkTimer = new TimeoutTimer(); - this._firstChunkTimer.setIfNotSet(() => { - acceptFirstDataChunk(); - }, 0); - this._socketDataListener = (data: Buffer) => { - acceptFirstDataChunk(); acceptChunk(data); }; _socket.on('data', this._socketDataListener); this._socketEndListener = () => { - acceptFirstDataChunk(); }; _socket.on('end', this._socketEndListener); @@ -146,7 +184,6 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { dispose(): void { this._isDisposed = true; - this._firstChunkTimer.dispose(); this._socket.removeListener('data', this._socketDataListener); this._socket.removeListener('end', this._socketEndListener); this._socket.removeListener('close', this._socketCloseListener); @@ -156,8 +193,8 @@ export class Protocol implements IDisposable, IMessagePassingProtocol { this._socket.end(); } - getBuffer(): Buffer { - return Buffer.concat(this._chunks); + readEntireBuffer(): Buffer { + return this._incomingData.read(this._incomingData.byteLength); } send(buffer: Buffer): void { diff --git a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts index 439dce11f52..5288308dc37 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts @@ -85,39 +85,4 @@ suite('IPC, Socket Protocol', () => { }); }); }); - - test('can devolve to a socket and evolve again without losing data', () => { - let resolve: (v: void) => void; - let result = new Promise((_resolve, _reject) => { - resolve = _resolve; - }); - const sender = new Protocol(stream); - const receiver1 = new Protocol(stream); - - assert.equal(stream.listenerCount('data'), 2); - assert.equal(stream.listenerCount('end'), 2); - - receiver1.onMessage((msg) => { - assert.equal(JSON.parse(msg.toString()).value, 1); - - let buffer = receiver1.getBuffer(); - receiver1.dispose(); - - assert.equal(stream.listenerCount('data'), 1); - assert.equal(stream.listenerCount('end'), 1); - - const receiver2 = new Protocol(stream, buffer); - receiver2.onMessage((msg) => { - assert.equal(JSON.parse(msg.toString()).value, 2); - resolve(undefined); - }); - }); - - const msg1 = { value: 1 }; - const msg2 = { value: 2 }; - sender.send(Buffer.from(JSON.stringify(msg1))); - sender.send(Buffer.from(JSON.stringify(msg2))); - - return result; - }); }); From dfb934c319e1392c1db1101a4774e3e6172efaea Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Mar 2019 10:17:07 +0100 Subject: [PATCH 143/172] Add a context key expression mapper --- .../platform/contextkey/common/contextkey.ts | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 6617af20f86..11d8132fe05 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -16,6 +16,14 @@ export const enum ContextKeyExprType { Regex = 6 } +export interface IContextKeyExprMapper { + mapDefined(key: string): ContextKeyDefinedExpr; + mapNot(key: string): ContextKeyNotExpr; + mapEquals(key: string, value: any): ContextKeyEqualsExpr; + mapNotEquals(key: string, value: any): ContextKeyNotEqualsExpr; + mapRegex(key: string, regexp: RegExp | null): ContextKeyRegexExpr; +} + export abstract class ContextKeyExpr { public static has(key: string): ContextKeyExpr { @@ -138,6 +146,7 @@ export abstract class ContextKeyExpr { public abstract normalize(): ContextKeyExpr | null; public abstract serialize(): string; public abstract keys(): string[]; + public abstract map(mapFnc: IContextKeyExprMapper): ContextKeyExpr; } function cmp(a: ContextKeyExpr, b: ContextKeyExpr): number { @@ -202,10 +211,14 @@ export class ContextKeyDefinedExpr implements ContextKeyExpr { public keys(): string[] { return [this.key]; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return mapFnc.mapDefined(this.key); + } } export class ContextKeyEqualsExpr implements ContextKeyExpr { - constructor(private key: string, private value: any) { + constructor(private readonly key: string, private readonly value: any) { } public getType(): ContextKeyExprType { @@ -263,6 +276,10 @@ export class ContextKeyEqualsExpr implements ContextKeyExpr { public keys(): string[] { return [this.key]; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return mapFnc.mapEquals(this.key, this.value); + } } export class ContextKeyNotEqualsExpr implements ContextKeyExpr { @@ -324,6 +341,10 @@ export class ContextKeyNotEqualsExpr implements ContextKeyExpr { public keys(): string[] { return [this.key]; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return mapFnc.mapNotEquals(this.key, this.value); + } } export class ContextKeyNotExpr implements ContextKeyExpr { @@ -366,6 +387,10 @@ export class ContextKeyNotExpr implements ContextKeyExpr { public keys(): string[] { return [this.key]; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return mapFnc.mapNot(this.key); + } } export class ContextKeyRegexExpr implements ContextKeyExpr { @@ -424,6 +449,10 @@ export class ContextKeyRegexExpr implements ContextKeyExpr { public keys(): string[] { return [this.key]; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return mapFnc.mapRegex(this.key, this.regexp); + } } export class ContextKeyAndExpr implements ContextKeyExpr { @@ -523,6 +552,10 @@ export class ContextKeyAndExpr implements ContextKeyExpr { } return result; } + + public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr { + return new ContextKeyAndExpr(this.expr.map(expr => expr.map(mapFnc))); + } } export class RawContextKey extends ContextKeyDefinedExpr { From 1d345f07379fc958f6f9da8d63489030353c2a1d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Mar 2019 10:18:56 +0100 Subject: [PATCH 144/172] URI always needs to be revived after crossing ipc boundaries --- .../electron-browser/mainThreadTerminalService.ts | 5 +++-- src/vs/workbench/api/node/extHost.protocol.ts | 8 ++++---- src/vs/workbench/api/node/extHostTerminalService.ts | 12 ++++++++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts b/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts index 3f30d465934..8a1fc7d216d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts @@ -7,6 +7,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY } from 'vs/workbench/contrib/terminal/common/terminal'; import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto } from 'vs/workbench/api/node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { UriComponents, URI } from 'vs/base/common/uri'; @extHostNamedCustomer(MainContext.MainThreadTerminalService) export class MainThreadTerminalService implements MainThreadTerminalServiceShape { @@ -58,12 +59,12 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape // when the extension host process goes down ? } - public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }> { + public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string | UriComponents, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }> { const shellLaunchConfig: IShellLaunchConfig = { name, executable: shellPath, args: shellArgs, - cwd, + cwd: typeof cwd === 'string' ? cwd : URI.revive(cwd), waitOnExit, ignoreConfigurationCwd: true, env, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 53df36fbf27..8d094cf262a 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -368,7 +368,7 @@ export interface MainThreadProgressShape extends IDisposable { } export interface MainThreadTerminalServiceShape extends IDisposable { - $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string | URI, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }>; + $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string | UriComponents, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }>; $createTerminalRenderer(name: string): Promise; $dispose(terminalId: number): void; $hide(terminalId: number): void; @@ -527,7 +527,7 @@ export interface ExtHostUrlsShape { } export interface MainThreadWorkspaceShape extends IDisposable { - $startFileSearch(includePattern: string | undefined, includeFolder: URI | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number, token: CancellationToken): Promise; + $startFileSearch(includePattern: string | undefined, includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number, token: CancellationToken): Promise; $startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise; $checkExists(includes: string[], token: CancellationToken): Promise; $saveAll(includeUntitled?: boolean): Promise; @@ -965,7 +965,7 @@ export interface ShellLaunchConfigDto { name?: string; executable?: string; args?: string[] | string; - cwd?: string | URI; + cwd?: string | UriComponents; env?: { [key: string]: string | null }; } @@ -978,7 +978,7 @@ export interface ExtHostTerminalServiceShape { $acceptTerminalRendererInput(id: number, data: string): void; $acceptTerminalTitleChange(id: number, name: string): void; $acceptTerminalDimensions(id: number, cols: number, rows: number): void; - $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: URI, cols: number, rows: number): void; + $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number): void; $acceptProcessInput(id: number, data: string): void; $acceptProcessResize(id: number, cols: number, rows: number): void; $acceptProcessShutdown(id: number, immediate: boolean): void; diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 070d8874c22..45d953bb808 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -13,7 +13,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; import { ILogService } from 'vs/platform/log/common/log'; -import { EXT_HOST_CREATION_DELAY } from 'vs/workbench/contrib/terminal/common/terminal'; +import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { timeout } from 'vs/base/common/async'; import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; @@ -411,7 +411,15 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { } } - public async $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): Promise { + public async $createProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): Promise { + const shellLaunchConfig: IShellLaunchConfig = { + name: shellLaunchConfigDto.name, + executable: shellLaunchConfigDto.executable, + args: shellLaunchConfigDto.args, + cwd: typeof shellLaunchConfigDto.cwd === 'string' ? shellLaunchConfigDto.cwd : URI.revive(shellLaunchConfigDto.cwd), + env: shellLaunchConfigDto.env + }; + // TODO: This function duplicates a lot of TerminalProcessManager.createProcess, ideally // they would be merged into a single implementation. const configProvider = await this._extHostConfiguration.getConfigProvider(); From 764d2e94873c299feb03a20dc1a8f584b1edc9ab Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 6 Mar 2019 10:28:54 +0100 Subject: [PATCH 145/172] fixes #67722 --- src/vs/base/browser/ui/tree/asyncDataTree.ts | 167 ++++++++---------- .../browser/ui/tree/asyncDataTree.test.ts | 137 ++++++++++++++ 2 files changed, 210 insertions(+), 94 deletions(-) diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index 20e0bdf0bd4..21b5b7fdef7 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -17,24 +17,35 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors'; import { toggleClass } from 'vs/base/browser/dom'; -const enum AsyncDataTreeNodeState { - Uninitialized = 'uninitialized', - Loaded = 'loaded', - Loading = 'loading' -} - interface IAsyncDataTreeNode { element: TInput | T; readonly parent: IAsyncDataTreeNode | null; readonly children: IAsyncDataTreeNode[]; readonly id?: string | null; - state: AsyncDataTreeNodeState; + loading: boolean; hasChildren: boolean; - needsRefresh: boolean; + stale: boolean; slow: boolean; disposed: boolean; } +interface IAsyncDataTreeNodeRequiredProps extends Partial> { + readonly element: TInput | T; + readonly parent: IAsyncDataTreeNode | null; + readonly hasChildren: boolean; +} + +function createAsyncDataTreeNode(props: IAsyncDataTreeNodeRequiredProps): IAsyncDataTreeNode { + return { + ...props, + children: [], + loading: false, + stale: true, + disposed: false, + slow: false + }; +} + function isAncestor(ancestor: IAsyncDataTreeNode, descendant: IAsyncDataTreeNode): boolean { if (!descendant.parent) { return false; @@ -236,7 +247,7 @@ function asTreeElement(node: IAsyncDataTreeNode, viewState return { element: node, - children: Iterator.map(Iterator.fromArray(node.children), child => asTreeElement(child, viewStateContext)), + children: node.hasChildren ? Iterator.map(Iterator.fromArray(node.children), child => asTreeElement(child, viewStateContext)) : [], collapsible: node.hasChildren, collapsed }; @@ -318,16 +329,11 @@ export class AsyncDataTree implements IDisposable this.tree = new ObjectTree(container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions); - this.root = { + this.root = createAsyncDataTreeNode({ element: undefined!, parent: null, - children: [], - state: AsyncDataTreeNodeState.Uninitialized, - hasChildren: true, - needsRefresh: false, - disposed: false, - slow: false - }; + hasChildren: true + }); if (this.identityProvider) { this.root = { @@ -426,7 +432,7 @@ export class AsyncDataTree implements IDisposable throw new Error('Tree input not set'); } - if (this.root.state === AsyncDataTreeNodeState.Loading) { + if (this.root.loading) { await this.subTreeRefreshPromises.get(this.root)!; await Event.toPromise(this._onDidRender.event); } @@ -477,20 +483,20 @@ export class AsyncDataTree implements IDisposable throw new Error('Tree input not set'); } - if (this.root.state === AsyncDataTreeNodeState.Loading) { + if (this.root.loading) { await this.subTreeRefreshPromises.get(this.root)!; await Event.toPromise(this._onDidRender.event); } const node = this.getDataNode(element); - if (node !== this.root && node.state !== AsyncDataTreeNodeState.Loading && !this.tree.isCollapsed(node)) { + if (node !== this.root && !node.loading && !this.tree.isCollapsed(node)) { return false; } const result = this.tree.expand(node === this.root ? null : node, recursive); - if (node.state === AsyncDataTreeNodeState.Loading) { + if (node.loading) { await this.subTreeRefreshPromises.get(node)!; await Event.toPromise(this._onDidRender.event); } @@ -651,39 +657,19 @@ export class AsyncDataTree implements IDisposable } private async doRefreshSubTree(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { - node.state = AsyncDataTreeNodeState.Loading; + node.loading = true; try { - await this.doRefreshNode(node, recursive, viewStateContext); + const childrenToRefresh = await this.doRefreshNode(node, recursive, viewStateContext); + node.stale = false; - if (recursive) { - const childrenToRefresh = node.children - .filter(child => { - if (child.needsRefresh) { - child.needsRefresh = false; - return true; - } - - // TODO@joao: is this still needed? - if (child.hasChildren && child.state === AsyncDataTreeNodeState.Loaded) { - return true; - } - - if (!viewStateContext || !viewStateContext.viewState.expanded || !child.id) { - return false; - } - - return viewStateContext.viewState.expanded.indexOf(child.id) > -1; - }); - - await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext))); - } + await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext))); } finally { - node.state = AsyncDataTreeNodeState.Loaded; + node.loading = false; } } - private async doRefreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { + private async doRefreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise[]> { node.hasChildren = !!this.dataSource.hasChildren(node.element!); let childrenPromise: Promise; @@ -704,16 +690,14 @@ export class AsyncDataTree implements IDisposable try { const children = await childrenPromise; - this.setChildren(node, children, recursive, viewStateContext); + return this.setChildren(node, children, recursive, viewStateContext); } catch (err) { - node.needsRefresh = true; - if (node !== this.root) { this.tree.collapse(node === this.root ? null : node); } if (isPromiseCanceledError(err)) { - return; + return []; } throw err; @@ -748,7 +732,7 @@ export class AsyncDataTree implements IDisposable } private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent, any>): void { - if (!node.collapsed && (node.element.state === AsyncDataTreeNodeState.Uninitialized || node.element.needsRefresh)) { + if (!node.collapsed && node.element.stale) { if (deep) { this.collapse(node.element.element as T); } else { @@ -758,7 +742,12 @@ export class AsyncDataTree implements IDisposable } } - private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): void { + private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): IAsyncDataTreeNode[] { + // perf: if the node was and still is a leaf, avoid all this hassle + if (node.children.length === 0 && childrenElements.length === 0) { + return []; + } + let nodeChildren: Map> | undefined; if (this.identityProvider) { @@ -769,67 +758,57 @@ export class AsyncDataTree implements IDisposable } } + let childrenToRefresh: IAsyncDataTreeNode[] = []; + const children = childrenElements.map>(element => { if (!this.identityProvider) { - const hasChildren = !!this.dataSource.hasChildren(element); - - return { + return createAsyncDataTreeNode({ element, parent: node, - children: [], - state: AsyncDataTreeNodeState.Uninitialized, - hasChildren, - needsRefresh: false, - disposed: false, - slow: false - }; + hasChildren: !!this.dataSource.hasChildren(element), + }); } const id = this.identityProvider.getId(element).toString(); const asyncDataTreeNode = nodeChildren!.get(id); - if (!asyncDataTreeNode) { - const childAsyncDataTreeNode: IAsyncDataTreeNode = { - element, - parent: node, - children: [], - id, - state: AsyncDataTreeNodeState.Uninitialized, - hasChildren: !!this.dataSource.hasChildren(element), - needsRefresh: false, - disposed: false, - slow: false - }; + if (asyncDataTreeNode) { + asyncDataTreeNode.element = element; + asyncDataTreeNode.stale = asyncDataTreeNode.stale || recursive; + asyncDataTreeNode.hasChildren = !!this.dataSource.hasChildren(element); - if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) { - viewStateContext.focus.push(childAsyncDataTreeNode); + if (recursive && !this.tree.isCollapsed(asyncDataTreeNode)) { + childrenToRefresh.push(asyncDataTreeNode); } - if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) { - viewStateContext.selection.push(childAsyncDataTreeNode); - } - - return childAsyncDataTreeNode; + return asyncDataTreeNode; } - asyncDataTreeNode.element = element; + const childAsyncDataTreeNode = createAsyncDataTreeNode({ + element, + parent: node, + id, + hasChildren: !!this.dataSource.hasChildren(element) + }); - const hasChildren = this.dataSource.hasChildren(asyncDataTreeNode.element); - - if (asyncDataTreeNode.state === AsyncDataTreeNodeState.Loaded || (asyncDataTreeNode.state !== AsyncDataTreeNodeState.Uninitialized && asyncDataTreeNode.hasChildren !== !!hasChildren)) { - asyncDataTreeNode.needsRefresh = true; + if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) { + viewStateContext.focus.push(childAsyncDataTreeNode); } - asyncDataTreeNode.hasChildren = hasChildren; - return asyncDataTreeNode; + if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) { + viewStateContext.selection.push(childAsyncDataTreeNode); + } + + if (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) { + childrenToRefresh.push(childAsyncDataTreeNode); + } + + return childAsyncDataTreeNode; }); - // perf: if the node was and still is a leaf, avoid all these expensive no-ops - if (node.children.length === 0 && childrenElements.length === 0) { - return; - } - node.children.splice(0, node.children.length, ...children); + + return childrenToRefresh; } private render(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): void { diff --git a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts index 6ceccbd08dc..3c934126df9 100644 --- a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts @@ -189,4 +189,141 @@ suite('AsyncDataTree', function () { assert(hasClass(twistie, 'collapsed')); assert(tree.getNode().children[0].collapsed); }); + + test('issue #67722 - once resolved, refreshed collapsed nodes should only get children when expanded', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const getChildrenCalls: string[] = []; + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + getChildrenCalls.push(element.id); + return Promise.resolve(element.children || []); + } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: Element) { + return element.id; + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }] + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { identityProvider }); + tree.layout(200); + + await tree.setInput(root); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root']); + + await tree.expand(_('a')); + assert(!tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a']); + + tree.collapse(_('a')); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a']); + + await tree.updateChildren(); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a', 'root'], 'a should not be refreshed, since it\' collapsed'); + }); + + test('resolved collapsed nodes which lose children should lose twistie as well', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + return Promise.resolve(element.children || []); + } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: Element) { + return element.id; + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }] + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { identityProvider }); + tree.layout(200); + + await tree.setInput(root); + await tree.expand(_('a')); + + let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(!tree.getNode(_('a')).collapsed); + + tree.collapse(_('a')); + _('a').children = []; + await tree.updateChildren(root); + + twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(!hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(tree.getNode(_('a')).collapsed); + }); }); \ No newline at end of file From e6bc6699a47f123533ea5338412cb6c780d0fdbb Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 6 Mar 2019 10:50:07 +0100 Subject: [PATCH 146/172] strict null checks: extHostSCM --- src/tsconfig.strictNullChecks.json | 1 + src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostSCM.ts | 27 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 21cb5fb6cae..0815dc052f9 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -97,6 +97,7 @@ "./vs/workbench/api/node/extHostOutputService.ts", "./vs/workbench/api/node/extHostProgress.ts", "./vs/workbench/api/node/extHostQuickOpen.ts", + "./vs/workbench/api/node/extHostSCM.ts", "./vs/workbench/api/node/extHostSearch.fileIndex.ts", "./vs/workbench/api/node/extHostSearch.ts", "./vs/workbench/api/node/extHostStorage.ts", diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 8d094cf262a..0d20d99f8e1 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -582,7 +582,7 @@ export interface SCMProviderFeatures { count?: number; commitTemplate?: string; acceptInputCommand?: modes.Command; - statusBarCommands?: modes.Command[]; + statusBarCommands?: CommandDto[]; } export interface SCMGroupFeatures { diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 226b62e4396..f0a48e6c2a5 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -10,7 +10,7 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { asPromise } from 'vs/base/common/async'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; -import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape } from './extHost.protocol'; +import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, CommandDto } from './extHost.protocol'; import { sortedDiff } from 'vs/base/common/arrays'; import { comparePaths } from 'vs/base/common/comparers'; import * as vscode from 'vscode'; @@ -23,7 +23,7 @@ type ProviderHandle = number; type GroupHandle = number; type ResourceStateHandle = number; -function getIconPath(decorations: vscode.SourceControlResourceThemableDecorations) { +function getIconPath(decorations?: vscode.SourceControlResourceThemableDecorations): string | undefined { if (!decorations) { return undefined; } else if (typeof decorations.iconPath === 'string') { @@ -60,7 +60,7 @@ function compareResourceStatesDecorations(a: vscode.SourceControlResourceDecorat } if (a.tooltip !== b.tooltip) { - return (a.tooltip || '').localeCompare(b.tooltip); + return (a.tooltip || '').localeCompare(b.tooltip || ''); } result = compareResourceThemableDecorations(a, b); @@ -205,7 +205,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { return this._visible; } - set visible(visible: boolean | undefined) { + set visible(visible: boolean) { visible = !!visible; this._visible = visible; this._proxy.$setInputBoxVisibility(this._sourceControlHandle, visible); @@ -287,7 +287,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG return Promise.resolve(undefined); } - return asPromise(() => this._commands.executeCommand(command.command, ...command.arguments)); + return asPromise(() => this._commands.executeCommand(command.command, ...(command.arguments || []))); } _takeResourceStateSnapshot(): SCMRawResourceSplice[] { @@ -309,11 +309,11 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG this._resourceStatesCommandsMap.set(handle, r.command); } - if (lightIconPath || darkIconPath) { + if (lightIconPath) { icons.push(lightIconPath); } - if (darkIconPath !== lightIconPath) { + if (darkIconPath && (darkIconPath !== lightIconPath)) { icons.push(darkIconPath); } @@ -442,7 +442,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this._statusBarCommands = statusBarCommands; - const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c)); + const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c)) as CommandDto[]; this._proxy.$updateSourceControl(this.handle, { statusBarCommands: internal }); } @@ -599,14 +599,12 @@ export class ExtHostSCM implements ExtHostSCMShape { } // Deprecated - getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox { + getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox | undefined { this.logService.trace('ExtHostSCM#getLastInputBox', extension.identifier.value); const sourceControls = this._sourceControlsByExtension.get(ExtensionIdentifier.toKey(extension.identifier)); const sourceControl = sourceControls && sourceControls[sourceControls.length - 1]; - const inputBox = sourceControl && sourceControl.inputBox; - - return inputBox; + return sourceControl && sourceControl.inputBox; } $provideOriginalResource(sourceControlHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise { @@ -615,11 +613,12 @@ export class ExtHostSCM implements ExtHostSCMShape { const sourceControl = this._sourceControls.get(sourceControlHandle); - if (!sourceControl || !sourceControl.quickDiffProvider) { + if (!sourceControl || !sourceControl.quickDiffProvider || !sourceControl.quickDiffProvider.provideOriginalResource) { return Promise.resolve(null); } - return asPromise(() => sourceControl.quickDiffProvider.provideOriginalResource(uri, token)); + return asPromise(() => sourceControl.quickDiffProvider!.provideOriginalResource!(uri, token)) + .then(r => r || null); } $onInputBoxValueChange(sourceControlHandle: number, value: string): Promise { From df93a3767fc74bd8e089ee64774e886e869f4a17 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 6 Mar 2019 11:47:05 +0100 Subject: [PATCH 147/172] fixes #69589 --- src/vs/workbench/browser/contextkeys.ts | 8 ++++++-- src/vs/workbench/browser/parts/editor/editorActions.ts | 2 +- src/vs/workbench/common/viewlet.ts | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 79e2037b343..e5e53f47ef6 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -17,7 +17,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EditorGroupsServiceImpl } from 'vs/workbench/browser/parts/editor/editor'; -import { SidebarVisibleContext } from 'vs/workbench/common/viewlet'; +import { SidebarVisibleContext, SideBarVisibleContext } from 'vs/workbench/common/viewlet'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -39,6 +39,8 @@ export class WorkbenchContextKeysHandler extends Disposable { private inZenModeContext: IContextKey; private sideBarVisibleContext: IContextKey; + //TODO@Isidor remove in May + private sidebarVisibleContext: IContextKey; constructor( @IContextKeyService private contextKeyService: IContextKeyService, @@ -127,7 +129,8 @@ export class WorkbenchContextKeysHandler extends Disposable { this.inZenModeContext = InEditorZenModeContext.bindTo(this.contextKeyService); // Sidebar - this.sideBarVisibleContext = SidebarVisibleContext.bindTo(this.contextKeyService); + this.sideBarVisibleContext = SideBarVisibleContext.bindTo(this.contextKeyService); + this.sidebarVisibleContext = SidebarVisibleContext.bindTo(this.contextKeyService); } private updateEditorContextKeys(): void { @@ -204,5 +207,6 @@ export class WorkbenchContextKeysHandler extends Disposable { private updateSideBarContextKeys(): void { this.sideBarVisibleContext.set(this.partService.isVisible(Parts.SIDEBAR_PART)); + this.sidebarVisibleContext.set(this.partService.isVisible(Parts.SIDEBAR_PART)); } } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 205fdcaac49..0ef54f44bf5 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -882,7 +882,7 @@ export class ResetGroupSizesAction extends Action { export class MaximizeGroupAction extends Action { static readonly ID = 'workbench.action.maximizeEditor'; - static readonly LABEL = nls.localize('maximizeEditor', "Maximize Editor Group and Hide Sidebar"); + static readonly LABEL = nls.localize('maximizeEditor', "Maximize Editor Group and Hide Side Bar"); constructor( id: string, diff --git a/src/vs/workbench/common/viewlet.ts b/src/vs/workbench/common/viewlet.ts index b213967decd..09836ae5e8a 100644 --- a/src/vs/workbench/common/viewlet.ts +++ b/src/vs/workbench/common/viewlet.ts @@ -7,6 +7,7 @@ import { IComposite } from 'vs/workbench/common/composite'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export const SidebarVisibleContext = new RawContextKey('sidebarVisible', false); +export const SideBarVisibleContext = new RawContextKey('sideBarVisible', false); export const SidebarFocusContext = new RawContextKey('sideBarFocus', false); export const ActiveViewletContext = new RawContextKey('activeViewlet', ''); From 97efb5af57f4454fb1f1866ce54e277eb17ef935 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 12:03:03 +0100 Subject: [PATCH 148/172] fix #68421 --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3679da9592b..8eddb0f8231 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": "2.0.6", + "gulp-tsb": "2.0.7", "gulp-tslint": "^8.1.3", "gulp-uglify": "^3.0.0", "gulp-vinyl-zip": "^2.1.2", @@ -150,4 +150,4 @@ "windows-mutex": "0.2.1", "windows-process-tree": "0.2.3" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 654114c0663..53dc4477514 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3944,10 +3944,10 @@ gulp-symdest@^1.1.1: queue "^3.1.0" vinyl-fs "^2.4.3" -gulp-tsb@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/gulp-tsb/-/gulp-tsb-2.0.6.tgz#2f8fbee9a81cf0da088744d6da2bca457f2893d1" - integrity sha512-tSIAPfU9rhbtwMgRWopipWFx3NZg943bCLPcP3LxQJ4KUkSdPVc2ZivCibMojw/7HwJUMjLWQ2NCN0yStTQP0g== +gulp-tsb@2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/gulp-tsb/-/gulp-tsb-2.0.7.tgz#0e8c5cc20643d304979a59e90a6448260b314eba" + integrity sha512-9cllqseEkotum/aWHnCTQX/ATD3kyEi1aVzkGp0AEe768uNuU1DqPzRxvyVrfuIPcdYUUvtvmKvEvgIMffNmNA== dependencies: ansi-colors "^1.0.1" fancy-log "^1.3.2" From cd816afcc9991de89ab8dd28cab73b47747ea2ea Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 6 Mar 2019 12:24:41 +0100 Subject: [PATCH 149/172] Take static arguments for the view descriptor ctor --- .../api/browser/viewsExtensionPoint.ts | 2 +- .../browser/parts/views/viewsViewlet.ts | 2 +- src/vs/workbench/common/views.ts | 3 +-- .../electron-browser/debug.contribution.ts | 10 ++++---- .../electron-browser/extensionsViewlet.ts | 22 ++++++++--------- .../contrib/files/browser/explorerViewlet.ts | 6 ++--- .../outline/browser/outline.contribution.ts | 2 +- .../contrib/scm/browser/scmViewlet.ts | 2 +- .../test/browser/parts/views/views.test.ts | 24 +++++++++---------- 9 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index 03232b7c297..07aabc3588e 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -377,7 +377,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { const viewDescriptor = { id: item.id, name: item.name, - ctor: CustomTreeViewPanel, + ctorDescriptor: { ctor: CustomTreeViewPanel }, when: ContextKeyExpr.deserialize(item.when), canToggleVisibility: true, collapsed: this.showCollapsed(container), diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 55b19d00586..804e934a8ce 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -178,7 +178,7 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView } protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): ViewletPanel { - return this.instantiationService.createInstance(viewDescriptor.ctor, options) as ViewletPanel; + return (this.instantiationService as any).createInstance(viewDescriptor.ctorDescriptor.ctor, ...(viewDescriptor.ctorDescriptor.arguments || []), options) as ViewletPanel; } protected getView(id: string): ViewletPanel { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 7d08589c1a7..236ffeacaa2 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -121,8 +121,7 @@ export interface IViewDescriptor { readonly name: string; - // TODO@Sandeep do we really need this?! - readonly ctor: any; + readonly ctorDescriptor: { ctor: any, arguments?: any[] }; readonly when?: ContextKeyExpr; diff --git a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts index fde17ef6833..631ccbbc368 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts @@ -112,11 +112,11 @@ Registry.as(PanelExtensions.Panels).registerPanel(new PanelDescri Registry.as(PanelExtensions.Panels).setDefaultPanelId(REPL_ID); // Register default debug views -ViewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), ctor: VariablesView, order: 10, weight: 40, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' } }], VIEW_CONTAINER); -ViewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctor: WatchExpressionsView, order: 20, weight: 10, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' } }], VIEW_CONTAINER); -ViewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctor: CallStackView, order: 30, weight: 30, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' } }], VIEW_CONTAINER); -ViewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctor: BreakpointsView, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' } }], VIEW_CONTAINER); -ViewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctor: LoadedScriptsView, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: CONTEXT_LOADED_SCRIPTS_SUPPORTED }], VIEW_CONTAINER); +ViewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), ctorDescriptor: { ctor: VariablesView }, order: 10, weight: 40, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' } }], VIEW_CONTAINER); +ViewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctorDescriptor: { ctor: WatchExpressionsView }, order: 20, weight: 10, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' } }], VIEW_CONTAINER); +ViewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctorDescriptor: { ctor: CallStackView }, order: 30, weight: 30, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' } }], VIEW_CONTAINER); +ViewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: { ctor: BreakpointsView }, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' } }], VIEW_CONTAINER); +ViewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: { ctor: LoadedScriptsView }, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: CONTEXT_LOADED_SCRIPTS_SUPPORTED }], VIEW_CONTAINER); // register action to open viewlet const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts index 1a2d50168ba..215268085ae 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsViewlet.ts @@ -114,7 +114,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: ExtensionsListView, + ctorDescriptor: { ctor: ExtensionsListView }, when: ContextKeyExpr.and(ContextKeyExpr.has('searchExtensions'), ContextKeyExpr.not('searchInstalledExtensions'), ContextKeyExpr.not('searchBuiltInExtensions'), ContextKeyExpr.not('recommendedExtensions'), ContextKeyExpr.not('groupByServersContext')), weight: 100 }; @@ -127,7 +127,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: EnabledExtensionsView, + ctorDescriptor: { ctor: EnabledExtensionsView }, when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions'), ContextKeyExpr.has('hasInstalledExtensions')), weight: 40, canToggleVisibility: true, @@ -142,7 +142,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: DisabledExtensionsView, + ctorDescriptor: { ctor: DisabledExtensionsView }, when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions'), ContextKeyExpr.has('hasInstalledExtensions')), weight: 10, canToggleVisibility: true, @@ -158,7 +158,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: ExtensionsListView, + ctorDescriptor: { ctor: ExtensionsListView }, when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions'), ContextKeyExpr.not('hasInstalledExtensions')), weight: 60, order: 1 @@ -169,7 +169,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return [{ id: `server.extensionsList.${server.authority}`, name: server.label, - ctor: GroupByServerExtensionsView, + ctorDescriptor: { ctor: GroupByServerExtensionsView }, when: ContextKeyExpr.has('groupByServersContext'), weight: 100 }]; @@ -183,7 +183,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: DefaultRecommendedExtensionsView, + ctorDescriptor: { ctor: DefaultRecommendedExtensionsView }, when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions'), ContextKeyExpr.has('defaultRecommendedExtensions')), weight: 40, order: 2, @@ -198,7 +198,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: RecommendedExtensionsView, + ctorDescriptor: { ctor: RecommendedExtensionsView }, when: ContextKeyExpr.has('recommendedExtensions'), weight: 50, canToggleVisibility: true, @@ -213,7 +213,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: WorkspaceRecommendedExtensionsView, + ctorDescriptor: { ctor: WorkspaceRecommendedExtensionsView }, when: ContextKeyExpr.and(ContextKeyExpr.has('recommendedExtensions'), ContextKeyExpr.has('nonEmptyWorkspace')), weight: 50, canToggleVisibility: true, @@ -226,7 +226,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: BuiltInExtensionsView, + ctorDescriptor: { ctor: BuiltInExtensionsView }, when: ContextKeyExpr.has('searchBuiltInExtensions'), weight: 100, canToggleVisibility: true @@ -238,7 +238,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: BuiltInThemesExtensionsView, + ctorDescriptor: { ctor: BuiltInThemesExtensionsView }, when: ContextKeyExpr.has('searchBuiltInExtensions'), weight: 100, canToggleVisibility: true @@ -250,7 +250,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio return { id, name: viewIdNameMappings[id], - ctor: BuiltInBasicsExtensionsView, + ctorDescriptor: { ctor: BuiltInBasicsExtensionsView }, when: ContextKeyExpr.has('searchBuiltInExtensions'), weight: 100, canToggleVisibility: true diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index b8c1d34f383..4ba23bcf745 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -99,7 +99,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: OpenEditorsView.ID, name: OpenEditorsView.NAME, - ctor: OpenEditorsView, + ctorDescriptor: { ctor: OpenEditorsView }, order: 0, when: OpenEditorsVisibleCondition, canToggleVisibility: true, @@ -114,7 +114,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: EmptyView.ID, name: EmptyView.NAME, - ctor: EmptyView, + ctorDescriptor: { ctor: EmptyView }, order: 1, canToggleVisibility: false }; @@ -124,7 +124,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: ExplorerView.ID, name: localize('folders', "Folders"), - ctor: ExplorerView, + ctorDescriptor: { ctor: ExplorerView }, order: 1, canToggleVisibility: false }; diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 7ac9a19b96f..8e787b1d4a6 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -14,7 +14,7 @@ import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymb const _outlineDesc = { id: OutlineViewId, name: localize('name', "Outline"), - ctor: OutlinePanel, + ctorDescriptor: { ctor: OutlinePanel }, canToggleVisibility: true, hideByDefault: false, collapsed: true, diff --git a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts index 39eeddba79a..203d662dfb5 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts @@ -1366,7 +1366,7 @@ export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewle const panelsToAdd: { panel: ViewletPanel, size: number, index: number }[] = []; for (const { viewDescriptor, collapsed, index, size } of added) { - const panel = this.instantiationService.createInstance(viewDescriptor.ctor, { + const panel = this.instantiationService.createInstance(viewDescriptor.ctorDescriptor.ctor, { id: viewDescriptor.id, title: viewDescriptor.name, actionRunner: this.getActionRunner(), diff --git a/src/vs/workbench/test/browser/parts/views/views.test.ts b/src/vs/workbench/test/browser/parts/views/views.test.ts index 11fd665875f..5b0dd4cc9af 100644 --- a/src/vs/workbench/test/browser/parts/views/views.test.ts +++ b/src/vs/workbench/test/browser/parts/views/views.test.ts @@ -63,7 +63,7 @@ suite('ContributableViewsModel', () => { const viewDescriptor: IViewDescriptor = { id: 'view1', - ctor: null, + ctorDescriptor: null, name: 'Test View 1' }; @@ -89,7 +89,7 @@ suite('ContributableViewsModel', () => { const viewDescriptor: IViewDescriptor = { id: 'view1', - ctor: null, + ctorDescriptor: null, name: 'Test View 1', when: ContextKeyExpr.equals('showview1', true) }; @@ -128,8 +128,8 @@ suite('ContributableViewsModel', () => { const model = new ContributableViewsModel(container, viewsService); const seq = new ViewDescriptorSequence(model); - const view1: IViewDescriptor = { id: 'view1', ctor: null, name: 'Test View 1' }; - const view2: IViewDescriptor = { id: 'view2', ctor: null, name: 'Test View 2', when: ContextKeyExpr.equals('showview2', true) }; + const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null, name: 'Test View 1' }; + const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null, name: 'Test View 2', when: ContextKeyExpr.equals('showview2', true) }; ViewsRegistry.registerViews([view1, view2], container); assert.deepEqual(model.visibleViewDescriptors, [view1], 'only view1 should be visible'); @@ -151,8 +151,8 @@ suite('ContributableViewsModel', () => { const model = new ContributableViewsModel(container, viewsService); const seq = new ViewDescriptorSequence(model); - const view1: IViewDescriptor = { id: 'view1', ctor: null, name: 'Test View 1', when: ContextKeyExpr.equals('showview1', true) }; - const view2: IViewDescriptor = { id: 'view2', ctor: null, name: 'Test View 2' }; + const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null, name: 'Test View 1', when: ContextKeyExpr.equals('showview1', true) }; + const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null, name: 'Test View 2' }; ViewsRegistry.registerViews([view1, view2], container); assert.deepEqual(model.visibleViewDescriptors, [view2], 'only view2 should be visible'); @@ -174,9 +174,9 @@ suite('ContributableViewsModel', () => { const model = new ContributableViewsModel(container, viewsService); const seq = new ViewDescriptorSequence(model); - const view1: IViewDescriptor = { id: 'view1', ctor: null, name: 'Test View 1', canToggleVisibility: true }; - const view2: IViewDescriptor = { id: 'view2', ctor: null, name: 'Test View 2', canToggleVisibility: true }; - const view3: IViewDescriptor = { id: 'view3', ctor: null, name: 'Test View 3', canToggleVisibility: true }; + const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null, name: 'Test View 1', canToggleVisibility: true }; + const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null, name: 'Test View 2', canToggleVisibility: true }; + const view3: IViewDescriptor = { id: 'view3', ctorDescriptor: null, name: 'Test View 3', canToggleVisibility: true }; ViewsRegistry.registerViews([view1, view2, view3], container); assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3]); @@ -219,9 +219,9 @@ suite('ContributableViewsModel', () => { const model = new ContributableViewsModel(container, viewsService); const seq = new ViewDescriptorSequence(model); - const view1: IViewDescriptor = { id: 'view1', ctor: null, name: 'Test View 1' }; - const view2: IViewDescriptor = { id: 'view2', ctor: null, name: 'Test View 2' }; - const view3: IViewDescriptor = { id: 'view3', ctor: null, name: 'Test View 3' }; + const view1: IViewDescriptor = { id: 'view1', ctorDescriptor: null, name: 'Test View 1' }; + const view2: IViewDescriptor = { id: 'view2', ctorDescriptor: null, name: 'Test View 2' }; + const view3: IViewDescriptor = { id: 'view3', ctorDescriptor: null, name: 'Test View 3' }; ViewsRegistry.registerViews([view1, view2, view3], container); assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3], 'model views should be OK'); From 4159cb41d37ad8844264b266e56082d49ac78044 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 6 Mar 2019 12:38:55 +0100 Subject: [PATCH 150/172] Fix #69205 --- src/vs/platform/files/common/files.ts | 58 +----------------- .../output/electron-browser/outputServices.ts | 61 +++++++++++++++++-- .../configuration/node/configuration.ts | 45 +++++++++----- 3 files changed, 89 insertions(+), 75 deletions(-) diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 069e926bb47..fa87bbd829f 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -8,68 +8,14 @@ import { URI } from 'vs/base/common/uri'; import * as glob from 'vs/base/common/glob'; import { isLinux } from 'vs/base/common/platform'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { startsWithIgnoreCase } from 'vs/base/common/strings'; -import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { isEqualOrParent, isEqual } from 'vs/base/common/resources'; import { isUndefinedOrNull } from 'vs/base/common/types'; -import { ThrottledDelayer } from 'vs/base/common/async'; export const IFileService = createDecorator('fileService'); -export class FileListener extends Disposable { - - private readonly _onDidContentChange = new Emitter(); - readonly onDidContentChange: Event = this._onDidContentChange.event; - - private watching: boolean = false; - private delayer: ThrottledDelayer; - private etag: string | undefined; - - constructor( - private readonly file: URI, - private readonly fileService: IFileService - ) { - super(); - this.delayer = new ThrottledDelayer(500); - } - - watch(eTag?: string): void { - if (!this.watching) { - this.etag = eTag; - this.poll(); - this.watching = true; - } - } - - private poll(): void { - const loop = () => this.doWatch().then(() => this.poll()); - this.delayer.trigger(loop); - } - - private doWatch(): Promise { - return this.fileService.resolveFile(this.file) - .then(stat => { - if (stat.etag !== this.etag) { - this.etag = stat.etag; - this._onDidContentChange.fire(stat); - } - }); - } - - unwatch(): void { - if (this.watching) { - this.delayer.cancel(); - this.watching = false; - } - } - - dispose(): void { - this.unwatch(); - super.dispose(); - } -} - export interface IResourceEncodings { getWriteEncoding(resource: URI, preferredEncoding?: string): string; } diff --git a/src/vs/workbench/contrib/output/electron-browser/outputServices.ts b/src/vs/workbench/contrib/output/electron-browser/outputServices.ts index 897620d45f8..60db5a4544d 100644 --- a/src/vs/workbench/contrib/output/electron-browser/outputServices.ts +++ b/src/vs/workbench/contrib/output/electron-browser/outputServices.ts @@ -26,7 +26,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { RunOnceScheduler, ThrottledDelayer } from 'vs/base/common/async'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Position } from 'vs/editor/common/core/position'; -import { IFileService, FileListener } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { IPanel } from 'vs/workbench/common/panel'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -277,12 +277,65 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out } } +class OutputFileListener extends Disposable { + + private readonly _onDidContentChange = new Emitter(); + readonly onDidContentChange: Event = this._onDidContentChange.event; + + private watching: boolean = false; + private syncDelayer: ThrottledDelayer; + private etag: string | undefined; + + constructor( + private readonly file: URI, + private readonly fileService: IFileService + ) { + super(); + this.syncDelayer = new ThrottledDelayer(500); + } + + watch(eTag: string | undefined): void { + if (!this.watching) { + this.etag = eTag; + this.poll(); + this.watching = true; + } + } + + private poll(): void { + const loop = () => this.doWatch().then(() => this.poll()); + this.syncDelayer.trigger(loop); + } + + private doWatch(): Promise { + return this.fileService.resolveFile(this.file) + .then(stat => { + if (stat.etag !== this.etag) { + this.etag = stat.etag; + this._onDidContentChange.fire(stat.size); + } + }); + } + + unwatch(): void { + if (this.watching) { + this.syncDelayer.cancel(); + this.watching = false; + } + } + + dispose(): void { + this.unwatch(); + super.dispose(); + } +} + /** * An output channel driven by a file and does not support appending messages. */ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChannel { - private readonly fileHandler: FileListener; + private readonly fileHandler: OutputFileListener; private updateInProgress: boolean = false; private etag: string | undefined = ''; @@ -297,8 +350,8 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann ) { super(outputChannelDescriptor, modelUri, fileService, modelService, modeService); - this.fileHandler = this._register(new FileListener(this.file, this.fileService)); - this._register(this.fileHandler.onDidContentChange(({ size }) => this.update(size))); + this.fileHandler = this._register(new OutputFileListener(this.file, this.fileService)); + this._register(this.fileHandler.onDidContentChange(size => this.update(size))); this._register(toDisposable(() => this.fileHandler.unwatch())); } diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index cf439e7a9ef..b10f358735a 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -12,7 +12,7 @@ import * as errors from 'vs/base/common/errors'; import * as collections from 'vs/base/common/collections'; import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { RunOnceScheduler, Delayer } from 'vs/base/common/async'; -import { FileChangeType, FileChangesEvent, IContent, IFileService, FileListener } from 'vs/platform/files/common/files'; +import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files'; import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels'; import { FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; @@ -219,21 +219,33 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat private workspaceConfig: URI | null = null; private readonly reloadConfigurationScheduler: RunOnceScheduler; - private fileListener: FileListener | null; - private fileListenerDisposables: IDisposable[] = []; constructor(private fileService: IFileService, from?: IWorkspaceConfiguration) { super(from); this.workspaceConfig = from && from.workspaceIdentifier ? from.workspaceIdentifier.configPath : null; + this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e))); this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50)); - this.listenToWorkspaceConfigurationFile(); - this._register(toDisposable(() => dispose(this.fileListenerDisposables))); + this.watchWorkspaceConfigurationFile(); + this._register(toDisposable(() => this.unWatchWorkspaceConfigurtionFile())); + } + + private watchWorkspaceConfigurationFile(): void { + if (this.workspaceConfig) { + this.fileService.watchFileChanges(this.workspaceConfig); + } + } + + private unWatchWorkspaceConfigurtionFile(): void { + if (this.workspaceConfig) { + this.fileService.unwatchFileChanges(this.workspaceConfig); + } } protected loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise { if (!(this.workspaceConfig && resources.isEqual(this.workspaceConfig, workspaceIdentifier.configPath))) { + this.unWatchWorkspaceConfigurtionFile(); this.workspaceConfig = workspaceIdentifier.configPath; - this.listenToWorkspaceConfigurationFile(); + this.watchWorkspaceConfigurationFile(); } return this.fileService.resolveContent(this.workspaceConfig) .then(content => content.value, e => { @@ -242,16 +254,19 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat }); } - private listenToWorkspaceConfigurationFile(): void { - if (this.fileListener) { - this.fileListenerDisposables = dispose(this.fileListenerDisposables); - this.fileListener = null; - } + private handleWorkspaceFileEvents(event: FileChangesEvent): void { if (this.workspaceConfig) { - this.fileListener = new FileListener(this.workspaceConfig, this.fileService); - this.fileListenerDisposables.push(this.fileListener); - this.fileListener.watch(); - this.fileListener.onDidContentChange(() => this.reloadConfigurationScheduler.schedule(), this, this.fileListenerDisposables); + const events = event.changes; + + let affectedByChanges = false; + // Find changes that affect workspace file + for (let i = 0, len = events.length; i < len && !affectedByChanges; i++) { + affectedByChanges = resources.isEqual(this.workspaceConfig, events[i].resource); + } + + if (affectedByChanges) { + this.reloadConfigurationScheduler.schedule(); + } } } } From 1b681fd98dc47888ee11764bfb7d7b6871ffe036 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 6 Mar 2019 12:43:19 +0100 Subject: [PATCH 151/172] showItemInFolder with URI --- src/vs/platform/windows/common/windows.ts | 2 +- src/vs/platform/windows/electron-main/windowsService.ts | 6 ++++-- src/vs/platform/windows/node/windowsIpc.ts | 4 ++-- src/vs/workbench/browser/parts/titlebar/titlebarPart.ts | 2 +- .../extensions/electron-browser/extensionsActions.ts | 6 +++--- .../contrib/files/browser/editors/binaryFileEditor.ts | 2 +- src/vs/workbench/contrib/files/browser/fileCommands.ts | 4 ++-- src/vs/workbench/contrib/logs/common/logsActions.ts | 3 ++- .../contrib/performance/electron-browser/startupProfiler.ts | 3 ++- src/vs/workbench/test/workbenchTestServices.ts | 2 +- 10 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index e28ca55477a..365c9200472 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -155,7 +155,7 @@ export interface IWindowsService { getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>; getWindowCount(): Promise; log(severity: string, ...messages: string[]): Promise; - showItemInFolder(path: string): Promise; + showItemInFolder(path: URI): Promise; getActiveWindowId(): Promise; // This needs to be handled from browser process to prevent diff --git a/src/vs/platform/windows/electron-main/windowsService.ts b/src/vs/platform/windows/electron-main/windowsService.ts index 016c59a3f20..33d89510c79 100644 --- a/src/vs/platform/windows/electron-main/windowsService.ts +++ b/src/vs/platform/windows/electron-main/windowsService.ts @@ -324,10 +324,12 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable console[severity].apply(console, ...messages); } - async showItemInFolder(path: string): Promise { + async showItemInFolder(path: URI): Promise { this.logService.trace('windowsService#showItemInFolder'); - shell.showItemInFolder(path); + if (path.scheme === Schemas.file) { + shell.showItemInFolder(path.fsPath); + } } async getActiveWindowId(): Promise { diff --git a/src/vs/platform/windows/node/windowsIpc.ts b/src/vs/platform/windows/node/windowsIpc.ts index 12b741138c0..bc726d9460e 100644 --- a/src/vs/platform/windows/node/windowsIpc.ts +++ b/src/vs/platform/windows/node/windowsIpc.ts @@ -95,7 +95,7 @@ export class WindowsChannel implements IServerChannel { case 'toggleSharedProcess': return this.service.toggleSharedProcess(); case 'quit': return this.service.quit(); case 'log': return this.service.log(arg[0], arg[1]); - case 'showItemInFolder': return this.service.showItemInFolder(arg); + case 'showItemInFolder': return this.service.showItemInFolder(URI.revive(arg)); case 'getActiveWindowId': return this.service.getActiveWindowId(); case 'openExternal': return this.service.openExternal(arg); case 'startCrashReporter': return this.service.startCrashReporter(arg); @@ -309,7 +309,7 @@ export class WindowsChannelClient implements IWindowsService { return this.channel.call('log', [severity, messages]); } - showItemInFolder(path: string): Promise { + showItemInFolder(path: URI): Promise { return this.channel.call('showItemInFolder', path); } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 9bb6b629cf9..d4fa3b061d8 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -617,7 +617,7 @@ class ShowItemInFolderAction extends Action { } run(): Promise { - return this.windowsService.showItemInFolder(this.path); + return this.windowsService.showItemInFolder(URI.file(this.path)); } } diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts index 32eb8cc1048..f063733ef90 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts @@ -2529,11 +2529,11 @@ export class OpenExtensionsFolderAction extends Action { const extensionsHome = URI.file(this.environmentService.extensionsPath); return Promise.resolve(this.fileService.resolveFile(extensionsHome)).then(file => { - let itemToShow: string; + let itemToShow: URI; if (file.children && file.children.length > 0) { - itemToShow = file.children[0].resource.fsPath; + itemToShow = file.children[0].resource; } else { - itemToShow = extensionsHome.fsPath; + itemToShow = extensionsHome; } return this.windowsService.showItemInFolder(itemToShow); diff --git a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts index 56e4ac1979b..854da7251dc 100644 --- a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts @@ -57,7 +57,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { private openExternal(resource: URI): void { this.windowsService.openExternal(resource.toString()).then(didOpen => { if (!didOpen) { - return this.windowsService.showItemInFolder(resource.fsPath); + return this.windowsService.showItemInFolder(resource); } return undefined; diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index d5483f119d8..734b84326b6 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -357,9 +357,9 @@ CommandsRegistry.registerCommand({ function revealResourcesInOS(resources: URI[], windowsService: IWindowsService, notificationService: INotificationService, workspaceContextService: IWorkspaceContextService): void { if (resources.length) { - sequence(resources.map(r => () => windowsService.showItemInFolder(r.fsPath))); + sequence(resources.map(r => () => windowsService.showItemInFolder(r))); } else if (workspaceContextService.getWorkspace().folders.length) { - windowsService.showItemInFolder(workspaceContextService.getWorkspace().folders[0].uri.fsPath); + windowsService.showItemInFolder(workspaceContextService.getWorkspace().folders[0].uri); } else { notificationService.info(nls.localize('openFileToReveal', "Open a file first to reveal")); } diff --git a/src/vs/workbench/contrib/logs/common/logsActions.ts b/src/vs/workbench/contrib/logs/common/logsActions.ts index faa6e33ec1e..56b54a4c89c 100644 --- a/src/vs/workbench/contrib/logs/common/logsActions.ts +++ b/src/vs/workbench/contrib/logs/common/logsActions.ts @@ -10,6 +10,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IWindowsService } from 'vs/platform/windows/common/windows'; import { ILogService, LogLevel, DEFAULT_LOG_LEVEL } from 'vs/platform/log/common/log'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { URI } from 'vs/base/common/uri'; export class OpenLogsFolderAction extends Action { @@ -24,7 +25,7 @@ export class OpenLogsFolderAction extends Action { } run(): Promise { - return this.windowsService.showItemInFolder(join(this.environmentService.logsPath, 'main.log')); + return this.windowsService.showItemInFolder(URI.file(join(this.environmentService.logsPath, 'main.log'))); } } diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts b/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts index dfd9214684a..8927080ea73 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts @@ -16,6 +16,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { PerfviewInput } from 'vs/workbench/contrib/performance/electron-browser/perfviewEditor'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { URI } from 'vs/base/common/uri'; export class StartupProfiler implements IWorkbenchContribution { @@ -78,7 +79,7 @@ export class StartupProfiler implements IWorkbenchContribution { }).then(res => { if (res.confirmed) { Promise.all([ - this._windowsService.showItemInFolder(join(dir, files[0])), + this._windowsService.showItemInFolder(URI.file(join(dir, files[0]))), this._createPerfIssue(files) ]).then(() => { // keep window stable until restart is selected diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 6f31697329d..a9ea758e590 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1332,7 +1332,7 @@ export class TestWindowsService implements IWindowsService { return Promise.resolve(); } - showItemInFolder(_path: string): Promise { + showItemInFolder(_path: URI): Promise { return Promise.resolve(); } From beca500a3878cdbc823fd8a571d2e3dfb8a97e30 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 12:07:45 +0100 Subject: [PATCH 152/172] debt - remove startup type logging --- .../performance/electron-browser/startupTimings.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts index 55020ca1872..fd937159d62 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts @@ -9,7 +9,6 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILifecycleService, StartupKind } from 'vs/platform/lifecycle/common/lifecycle'; -import { ILogService } from 'vs/platform/log/common/log'; import product from 'vs/platform/product/node/product'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService } from 'vs/platform/update/common/update'; @@ -24,7 +23,6 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; export class StartupTimings implements IWorkbenchContribution { constructor( - @ILogService private readonly _logService: ILogService, @ITimerService private readonly _timerService: ITimerService, @IWindowsService private readonly _windowsService: IWindowsService, @IEditorService private readonly _editorService: IEditorService, @@ -88,36 +86,28 @@ export class StartupTimings implements IWorkbenchContribution { // * one text editor (not multiple, not webview, welcome etc...) // * cached data present (not rejected, not created) if (this._lifecycleService.startupKind !== StartupKind.NewWindow) { - this._logService.info('no standard startup: not a new window'); return false; } if (await this._windowsService.getWindowCount() !== 1) { - this._logService.info('no standard startup: not just one window'); return false; } const activeViewlet = this._viewletService.getActiveViewlet(); if (!activeViewlet || activeViewlet.getId() !== files.VIEWLET_ID) { - this._logService.info('no standard startup: not the explorer viewlet'); return false; } const visibleControls = this._editorService.visibleControls; if (visibleControls.length !== 1 || !isCodeEditor(visibleControls[0].getControl())) { - this._logService.info('no standard startup: not just one text editor'); return false; } if (this._panelService.getActivePanel()) { - this._logService.info('no standard startup: panel is active'); return false; } if (!didUseCachedData()) { - this._logService.info('no standard startup: not using cached data'); return false; } if (!await this._updateService.isLatestVersion()) { - this._logService.info('no standard startup: not running latest version'); return false; } - this._logService.info('standard startup'); return true; } } From 74955b29d7804cf3fe1fcde264c4d7f7cb926856 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 12:15:53 +0100 Subject: [PATCH 153/172] send raw timer ticks, #67650 --- .../performance/electron-browser/startupTimings.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts index fd937159d62..2af7ea08c5b 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts @@ -19,6 +19,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { didUseCachedData, ITimerService } from 'vs/workbench/services/timer/electron-browser/timerService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { getEntries } from 'vs/base/common/performance'; export class StartupTimings implements IWorkbenchContribution { @@ -41,6 +42,7 @@ export class StartupTimings implements IWorkbenchContribution { const isStandardStartup = await this._isStandardStartup(); this._reportStartupTimes().catch(onUnexpectedError); this._appendStartupTimes(isStandardStartup).catch(onUnexpectedError); + this._reportPerfTicks(); } private async _reportStartupTimes(): Promise { @@ -110,5 +112,11 @@ export class StartupTimings implements IWorkbenchContribution { } return true; } + + private _reportPerfTicks(): void { + const entries = getEntries(); + //todo@joh proper data declare + this._telemetryService.publicLog('startupRawTimers', entries); + } } From 0fa822f7d5fafd0623aff80cb97e3cea1e2b2ae3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 14:52:29 +0100 Subject: [PATCH 154/172] add newline and warning-icon before the path, #69044 --- .../extensions/electron-browser/runtimeExtensionsEditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index da6880ff9b7..dcc921a7168 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -524,7 +524,7 @@ export class ReportExtensionIssueAction extends Action { const data = profiler.rewriteAbsolutePaths({ profile: extension.unresponsiveProfile!.data }, 'pii_removed'); profiler.writeProfile(data, path).then(undefined, onUnexpectedError); }; - message = `:warning: Make sure to **attach** this file from your *home*-directory: \`${path}\` :warning:\n\nFind more details here: https://github.com/Microsoft/vscode/wiki/Explain:-extension-causes-high-cpu-load`; + message = `:warning: Make sure to **attach** this file from your *home*-directory:\n:warning:\`${path}\`\n\nFind more details here: https://github.com/Microsoft/vscode/wiki/Explain:-extension-causes-high-cpu-load`; } else { // generic From 26f0a77c56ef675072aa3ed6b19987cb89e13fd2 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 6 Mar 2019 15:09:20 +0100 Subject: [PATCH 155/172] Make simple file picker case insensitive Fixes #69796 --- .../dialogs/electron-browser/remoteFileDialog.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts index 50395ba25f6..08f9ea471b8 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts @@ -214,7 +214,7 @@ export class RemoteFileDialog { if (value !== this.userValue) { const trimmedPickBoxValue = ((this.filePickBox.value.length > 1) && this.endsWithSlash(this.filePickBox.value)) ? this.filePickBox.value.substr(0, this.filePickBox.value.length - 1) : this.filePickBox.value; const valueUri = this.remoteUriFrom(trimmedPickBoxValue); - if (!resources.isEqual(this.currentFolder, valueUri)) { + if (!resources.isEqual(this.currentFolder, valueUri, true)) { await this.tryUpdateItems(value, valueUri); } this.setActiveItems(value); @@ -256,7 +256,7 @@ export class RemoteFileDialog { // Find resolve value if (this.filePickBox.activeItems.length === 0) { - if (!this.requiresTrailing && resources.isEqual(this.currentFolder, inputUri)) { + if (!this.requiresTrailing && resources.isEqual(this.currentFolder, inputUri, true)) { resolveValue = inputUri; } else if (this.requiresTrailing && statDirname && statDirname.isDirectory) { resolveValue = inputUri; @@ -288,7 +288,7 @@ export class RemoteFileDialog { } private async tryUpdateItems(value: string, valueUri: URI) { - if (this.endsWithSlash(value) || (!resources.isEqual(this.currentFolder, resources.dirname(valueUri)) && resources.isEqualOrParent(this.currentFolder, resources.dirname(valueUri)))) { + if (this.endsWithSlash(value) || (!resources.isEqual(this.currentFolder, resources.dirname(valueUri), true) && resources.isEqualOrParent(this.currentFolder, resources.dirname(valueUri), true))) { let stat: IFileStat | undefined; try { stat = await this.remoteFileService.resolveFile(valueUri); @@ -299,7 +299,7 @@ export class RemoteFileDialog { this.updateItems(valueUri); } else { const inputUriDirname = resources.dirname(valueUri); - if (!resources.isEqual(this.currentFolder, inputUriDirname)) { + if (!resources.isEqual(this.currentFolder, inputUriDirname, true)) { let statWithoutTrailing: IFileStat | undefined; try { statWithoutTrailing = await this.remoteFileService.resolveFile(inputUriDirname); @@ -321,7 +321,7 @@ export class RemoteFileDialog { for (let i = 0; i < this.filePickBox.items.length; i++) { const item = this.filePickBox.items[i]; const itemBasename = resources.basename(item.uri); - if ((itemBasename.length >= inputBasename.length) && (itemBasename.substr(0, inputBasename.length) === inputBasename)) { + if ((itemBasename.length >= inputBasename.length) && (itemBasename.substr(0, inputBasename.length).toLowerCase() === inputBasename.toLowerCase())) { this.filePickBox.activeItems = [item]; this.filePickBox.value = this.filePickBox.value + itemBasename.substr(inputBasename.length); this.filePickBox.valueSelection = [value.length, this.filePickBox.value.length]; @@ -442,7 +442,7 @@ export class RemoteFileDialog { private createBackItem(currFolder: URI): FileQuickPickItem | null { const parentFolder = resources.dirname(currFolder)!; - if (!resources.isEqual(currFolder, parentFolder)) { + if (!resources.isEqual(currFolder, parentFolder, true)) { return { label: '..', uri: resources.dirname(currFolder), isFolder: true }; } return null; From 40905b95ac88cea03619a4fe4a39edcea00a2594 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 15:23:00 +0100 Subject: [PATCH 156/172] eng - strict null checks for remoteFileService --- src/tsconfig.strictNullChecks.json | 3 +- src/vs/platform/files/common/files.ts | 2 +- .../externalTerminal.contribution.ts | 2 +- .../contrib/stats/node/workspaceStats.ts | 4 +- .../services/files/node/remoteFileService.ts | 87 +++++++++---------- 5 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 0815dc052f9..9ececdd3e50 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -433,6 +433,7 @@ "./vs/workbench/services/extensions/node/rpcProtocol.ts", "./vs/workbench/services/extensions/test/node/rpcProtocol.test.ts", "./vs/workbench/services/files/node/encoding.ts", + "./vs/workbench/services/files/node/remoteFileService.ts", "./vs/workbench/services/files/node/fileService.ts", "./vs/workbench/services/files/node/streams.ts", "./vs/workbench/services/files/test/electron-browser/utils.ts", @@ -521,4 +522,4 @@ "./typings/require-monaco.d.ts", "./vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts" ] -} \ No newline at end of file +} diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index fa87bbd829f..399a6001e09 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -455,7 +455,7 @@ export interface IFileStat extends IBaseStat { } export interface IResolveFileResult { - stat: IFileStat; + stat?: IFileStat; success: boolean; } diff --git a/src/vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution.ts b/src/vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution.ts index d72561ce0a0..34c5c845166 100644 --- a/src/vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution.ts +++ b/src/vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution.ts @@ -91,7 +91,7 @@ CommandsRegistry.registerCommand({ const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService); return fileService.resolveFiles(resources.map(r => ({ resource: r }))).then(stats => { - const directoriesToOpen = distinct(stats.map(({ stat }) => stat.isDirectory ? stat.resource.fsPath : paths.dirname(stat.resource.fsPath))); + const directoriesToOpen = distinct(stats.filter(data => data.success).map(({ stat }) => stat!.isDirectory ? stat!.resource.fsPath : paths.dirname(stat!.resource.fsPath))); return directoriesToOpen.map(dir => { if (configurationService.getValue().terminal.explorerKind === 'integrated') { const instance = integratedTerminalService.createTerminal({ cwd: dir }, true); diff --git a/src/vs/workbench/contrib/stats/node/workspaceStats.ts b/src/vs/workbench/contrib/stats/node/workspaceStats.ts index 10ea1691f99..ea4cc981bee 100644 --- a/src/vs/workbench/contrib/stats/node/workspaceStats.ts +++ b/src/vs/workbench/contrib/stats/node/workspaceStats.ts @@ -368,7 +368,7 @@ export class WorkspaceStats implements IWorkbenchContribution { } return this.fileService.resolveFiles(folders.map(resource => ({ resource }))).then((files: IResolveFileResult[]) => { - const names = ([]).concat(...files.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); + const names = ([]).concat(...files.map(result => result.success ? (result.stat!.children || []) : [])).map(c => c.name); const nameSet = names.reduce((s, n) => s.add(n.toLowerCase()), new Set()); if (participant) { @@ -664,7 +664,7 @@ export class WorkspaceStats implements IWorkbenchContribution { }); return this.fileService.resolveFiles(uris.map(resource => ({ resource }))).then( results => { - const names = ([]).concat(...results.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); + const names = ([]).concat(...results.map(result => result.success ? (result.stat!.children || []) : [])).map(c => c.name); const referencesAzure = WorkspaceStats.searchArray(names, /azure/i); if (referencesAzure) { tags['node'] = true; diff --git a/src/vs/workbench/services/files/node/remoteFileService.ts b/src/vs/workbench/services/files/node/remoteFileService.ts index e9beb32812c..36687a83c68 100644 --- a/src/vs/workbench/services/files/node/remoteFileService.ts +++ b/src/vs/workbench/services/files/node/remoteFileService.ts @@ -70,7 +70,7 @@ function toIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], recurse return Promise.resolve(fileStat); } -export function toDeepIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], to: URI[]): Promise { +export function toDeepIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], to?: URI[]): Promise { const trie = TernarySearchTree.forPaths(); trie.set(tuple[0].toString(), true); @@ -281,7 +281,7 @@ export class RemoteFileService extends FileService { FileOperationResult.FILE_NOT_FOUND ); } else { - return data[0].stat; + return data[0].stat!; } }); } @@ -319,7 +319,7 @@ export class RemoteFileService extends FileService { return toDeepIFileStat(provider, [item.resource, stat], item.options && item.options.resolveTo).then(fileStat => { result[idx] = { stat: fileStat, success: true }; }); - }, err => { + }, _err => { result[idx] = { stat: undefined, success: false }; }); }); @@ -440,7 +440,7 @@ export class RemoteFileService extends FileService { return RemoteFileService._mkdirp(provider, resources.dirname(resource)).then(() => { const encoding = this.encoding.getWriteEncoding(resource); - return this._writeFile(provider, resource, new StringSnapshot(content), encoding, { create: true, overwrite: Boolean(options && options.overwrite) }); + return this._writeFile(provider, resource, new StringSnapshot(content || ''), encoding, { create: true, overwrite: Boolean(options && options.overwrite) }); }); }).then(fileStat => { @@ -449,7 +449,7 @@ export class RemoteFileService extends FileService { }, err => { const message = localize('err.create', "Failed to create file {0}", resource.toString(false)); const result = this._tryParseFileOperationResult(err); - throw new FileOperationError(message, result, options); + throw new FileOperationError(message, result || -1, options); }); } } @@ -467,7 +467,7 @@ export class RemoteFileService extends FileService { } } - private _writeFile(provider: IFileSystemProvider, resource: URI, snapshot: ITextSnapshot, preferredEncoding: string, options: FileWriteOptions): Promise { + private _writeFile(provider: IFileSystemProvider, resource: URI, snapshot: ITextSnapshot, preferredEncoding: string | undefined = undefined, options: FileWriteOptions): Promise { const readable = createReadableOfSnapshot(snapshot); const encoding = this.encoding.getWriteEncoding(resource, preferredEncoding); const encoder = encodeStream(encoding); @@ -549,13 +549,13 @@ export class RemoteFileService extends FileService { } } - private _doMoveWithInScheme(source: URI, target: URI, overwrite?: boolean): Promise { + private async _doMoveWithInScheme(source: URI, target: URI, overwrite: boolean = false): Promise { - const prepare = overwrite - ? Promise.resolve(this.del(target, { recursive: true }).then(undefined, err => { /*ignore*/ })) - : Promise.resolve(null); + if (overwrite) { + await this.del(target, { recursive: true }).catch(_err => { /*ignore*/ }); + } - return prepare.then(() => this._withProvider(source)).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { + return this._withProvider(source).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { return RemoteFileService._mkdirp(provider, resources.dirname(target)).then(() => { return provider.rename(source, target, { overwrite }).then(() => { return this.resolveFile(target); @@ -589,11 +589,11 @@ export class RemoteFileService extends FileService { return super.copyFile(source, target, overwrite); } - return this._withProvider(target).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { + return this._withProvider(target).then(RemoteFileService._throwIfFileSystemIsReadonly).then(async provider => { if (source.scheme === target.scheme && (provider.capabilities & FileSystemProviderCapabilities.FileFolderCopy)) { // good: provider supports copy withing scheme - return provider.copy(source, target, { overwrite: !!overwrite }).then(() => { + return provider.copy!(source, target, { overwrite: !!overwrite }).then(() => { return this.resolveFile(target); }).then(fileStat => { this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); @@ -607,51 +607,46 @@ export class RemoteFileService extends FileService { }); } - const prepare = overwrite - ? Promise.resolve(this.del(target, { recursive: true }).then(undefined, err => { /*ignore*/ })) - : Promise.resolve(null); + if (overwrite) { + await this.del(target, { recursive: true }).catch(_err => { /*ignore*/ }); + } - return prepare.then(() => { - // todo@ben, can only copy text files - // https://github.com/Microsoft/vscode/issues/41543 - return this.resolveContent(source, { acceptTextOnly: true }).then(content => { - return this._withProvider(target).then(provider => { - return this._writeFile( - provider, target, - new StringSnapshot(content.value), - content.encoding, - { create: true, overwrite: !!overwrite } - ).then(fileStat => { - this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); - return fileStat; - }); - }, err => { - const result = this._tryParseFileOperationResult(err); - if (result === FileOperationResult.FILE_MOVE_CONFLICT) { - throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); - } else if (err instanceof Error && err.name === 'ENOPRO') { - // file scheme - return super.updateContent(target, content.value, { encoding: content.encoding }); - } else { - return Promise.reject(err); - } + // todo@ben, can only copy text files + // https://github.com/Microsoft/vscode/issues/41543 + return this.resolveContent(source, { acceptTextOnly: true }).then(content => { + return this._withProvider(target).then(provider => { + return this._writeFile( + provider, target, + new StringSnapshot(content.value), + content.encoding, + { create: true, overwrite: !!overwrite } + ).then(fileStat => { + this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); + return fileStat; }); + }, err => { + const result = this._tryParseFileOperationResult(err); + if (result === FileOperationResult.FILE_MOVE_CONFLICT) { + throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); + } else if (err instanceof Error && err.name === 'ENOPRO') { + // file scheme + return super.updateContent(target, content.value, { encoding: content.encoding }); + } else { + return Promise.reject(err); + } }); }); + }); } private _activeWatches = new Map, count: number }>(); - watchFileChanges(resource: URI, opts?: IWatchOptions): void { + watchFileChanges(resource: URI, opts: IWatchOptions = { recursive: false, excludes: [] }): void { if (resource.scheme === Schemas.file) { return super.watchFileChanges(resource); } - if (!opts) { - opts = { recursive: false, excludes: [] }; - } - const key = resource.toString(); const entry = this._activeWatches.get(key); if (entry) { @@ -663,7 +658,7 @@ export class RemoteFileService extends FileService { count: 1, unwatch: this._withProvider(resource).then(provider => { return provider.watch(resource, opts); - }, err => { + }, _err => { return { dispose() { } }; }) }); From 95e877dbcf6bec4f34eb6280fd089ccabe048d43 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 6 Mar 2019 16:12:43 +0100 Subject: [PATCH 157/172] more declarative service --- .../browser/parts/editor/editorPart.ts | 6 +- .../workbench/electron-browser/workbench.ts | 95 +++++++++++-------- .../editor/common/editorGroupsService.ts | 5 + .../services/title/common/titleService.ts | 6 ++ .../workbench/test/workbenchTestServices.ts | 1 + 5 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 4bcee05cf65..11037593d72 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -101,6 +101,9 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor private readonly _onDidActiveGroupChange: Emitter = this._register(new Emitter()); get onDidActiveGroupChange(): Event { return this._onDidActiveGroupChange.event; } + private readonly _onDidActivateGroup: Emitter = this._register(new Emitter()); + get onDidActivateGroup(): Event { return this._onDidActivateGroup.event; } + private readonly _onDidAddGroup: Emitter = this._register(new Emitter()); get onDidAddGroup(): Event { return this._onDidAddGroup.event; } @@ -117,9 +120,6 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor private readonly _onDidPreferredSizeChange: Emitter = this._register(new Emitter()); get onDidPreferredSizeChange(): Event { return this._onDidPreferredSizeChange.event; } - private readonly _onDidActivateGroup: Emitter = this._register(new Emitter()); - get onDidActivateGroup(): Event { return this._onDidActivateGroup.event; } - //#endregion private dimension: Dimension; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 39de9310f86..923b1bd1575 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -187,8 +187,6 @@ export class Workbench extends Disposable implements IPartService { private editorService: EditorService; private editorGroupService: IEditorGroupsService; - private contextViewService: ContextViewService; - private windowService: IWindowService; private instantiationService: IInstantiationService; private contextService: IWorkspaceContextService; @@ -326,8 +324,10 @@ export class Workbench extends Disposable implements IPartService { this._register(this.instantiationService.createInstance(WorkbenchContextKeysHandler)); // Register Listeners - this.registerListeners(); - this.registerLayoutListeners(); + this.instantiationService.invokeFunction(accessor => { + this.registerListeners(accessor); + this.registerLayoutListeners(accessor); + }); // Layout State this.instantiationService.invokeFunction(accessor => this.initLayoutState(accessor)); @@ -357,7 +357,7 @@ export class Workbench extends Disposable implements IPartService { private initServices(serviceCollection: ServiceCollection): void { // Parts - serviceCollection.set(IPartService, this); + serviceCollection.set(IPartService, this); // TODO@Ben use SyncDescriptor // Labels serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true)); @@ -366,12 +366,11 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(INotificationService, new SyncDescriptor(NotificationService, undefined, true)); // Window - this.windowService = this.instantiationService.createInstance(WindowService, this.configuration); - serviceCollection.set(IWindowService, this.windowService); + serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, [this.configuration])); // Product const productService = new ProductService(); - serviceCollection.set(IProductService, productService); + serviceCollection.set(IProductService, productService); // TODO@Ben use SyncDescriptor // Shared Process const sharedProcess = this.windowsService.whenSharedProcessReady() @@ -397,16 +396,10 @@ export class Workbench extends Disposable implements IPartService { telemetryService = NullTelemetryService; } - serviceCollection.set(ITelemetryService, telemetryService); + serviceCollection.set(ITelemetryService, telemetryService); // TODO@Ben use SyncDescriptor // Lifecycle - const lifecycleService = this.instantiationService.createInstance(LifecycleService); - serviceCollection.set(ILifecycleService, lifecycleService); - this._register(lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event))); - this._register(lifecycleService.onShutdown(() => { - this._onShutdown.fire(); - this.dispose(); - })); + serviceCollection.set(ILifecycleService, new SyncDescriptor(LifecycleService)); // Request Service serviceCollection.set(IRequestService, new SyncDescriptor(RequestService, undefined, true)); @@ -459,7 +452,7 @@ export class Workbench extends Disposable implements IPartService { // Status bar this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART); - serviceCollection.set(IStatusbarService, this.statusbarPart); + serviceCollection.set(IStatusbarService, this.statusbarPart); // TODO@Ben use SyncDescriptor // Context Keys serviceCollection.set(IContextKeyService, new SyncDescriptor(ContextKeyService)); @@ -468,8 +461,7 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IKeybindingService, new SyncDescriptor(WorkbenchKeybindingService, [window])); // Context view service - this.contextViewService = this.instantiationService.createInstance(ContextViewService, this.workbench); - serviceCollection.set(IContextViewService, this.contextViewService); + serviceCollection.set(IContextViewService, new SyncDescriptor(ContextViewService, [this.workbench], true)); // Use themable context menus when custom titlebar is enabled to match custom menubar if (!isMacintosh && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { @@ -478,15 +470,13 @@ export class Workbench extends Disposable implements IPartService { serviceCollection.set(IContextMenuService, new SyncDescriptor(NativeContextMenuService)); } - // Sidebar part + // Viewlet service (sidebar part) this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART); - - // Viewlet service - serviceCollection.set(IViewletService, this.sidebarPart); + serviceCollection.set(IViewletService, this.sidebarPart); // TODO@Ben use SyncDescriptor // Panel service (panel part) this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART); - serviceCollection.set(IPanelService, this.panelPart); + serviceCollection.set(IPanelService, this.panelPart); // TODO@Ben use SyncDescriptor // Views service serviceCollection.set(IViewsService, new SyncDescriptor(ViewsService)); @@ -501,27 +491,27 @@ export class Workbench extends Disposable implements IPartService { // Editor and Group services this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, !this.hasInitialFilesToOpen()); this.editorGroupService = this.editorPart; - serviceCollection.set(IEditorGroupsService, this.editorPart); + serviceCollection.set(IEditorGroupsService, this.editorPart); // TODO@Ben use SyncDescriptor this.editorService = this.instantiationService.createInstance(EditorService); - serviceCollection.set(IEditorService, this.editorService); + serviceCollection.set(IEditorService, this.editorService); // TODO@Ben use SyncDescriptor // Accessibility serviceCollection.set(IAccessibilityService, new SyncDescriptor(AccessibilityService, undefined, true)); // Title bar this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART); - serviceCollection.set(ITitleService, this.titlebarPart); + serviceCollection.set(ITitleService, this.titlebarPart); // TODO@Ben use SyncDescriptor // History serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService)); // Quick open service (quick open controller) this.quickOpen = this.instantiationService.createInstance(QuickOpenController); - serviceCollection.set(IQuickOpenService, this.quickOpen); + serviceCollection.set(IQuickOpenService, this.quickOpen); // TODO@Ben use SyncDescriptor // Quick input service this.quickInput = this.instantiationService.createInstance(QuickInputService); - serviceCollection.set(IQuickInputService, this.quickInput); + serviceCollection.set(IQuickInputService, this.quickInput); // TODO@Ben use SyncDescriptor // Contributed services const contributedServices = getServices(); @@ -575,13 +565,23 @@ export class Workbench extends Disposable implements IPartService { (this.configuration.filesToDiff && this.configuration.filesToDiff.length > 0)); } - private registerListeners(): void { + private registerListeners(accessor: ServicesAccessor): void { + const lifecycleService = accessor.get(ILifecycleService); + const storageService = accessor.get(IStorageService); + const configurationService = accessor.get(IConfigurationService); + + // Lifecycle + this._register(lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event))); + this._register(lifecycleService.onShutdown(() => { + this._onShutdown.fire(); + this.dispose(); + })); // Storage - this._register(this.storageService.onWillSaveState(e => this.saveState(e))); + this._register(storageService.onWillSaveState(e => this.saveState(e))); // Configuration changes - this._register(this.configurationService.onDidChangeConfiguration(() => this.setFontAliasing())); + this._register(configurationService.onDidChangeConfiguration(() => this.setFontAliasing())); } private fontAliasing: 'default' | 'antialiased' | 'none' | 'auto'; @@ -837,6 +837,9 @@ export class Workbench extends Disposable implements IPartService { private editorPartView: View; private statusBarPartView: View; + private contextViewService: IContextViewService; + private windowService: IWindowService; + private readonly state = { fullscreen: false, @@ -886,31 +889,37 @@ export class Workbench extends Disposable implements IPartService { } }; - private registerLayoutListeners(): void { + private registerLayoutListeners(accessor: ServicesAccessor): void { + const storageService = accessor.get(IStorageService); + const editorService = accessor.get(IEditorService); + const configurationService = accessor.get(IConfigurationService); + const editorGroupService = accessor.get(IEditorGroupsService); + const titleService = accessor.get(ITitleService); + const environmentService = accessor.get(IEnvironmentService); // Storage - this._register(this.storageService.onWillSaveState(e => this.saveLayoutState(e))); + this._register(storageService.onWillSaveState(e => this.saveLayoutState(e))); // Restore editor if hidden and it changes - this._register(this.editorService.onDidVisibleEditorsChange(() => this.setEditorHidden(false))); - this._register(this.editorPart.onDidActivateGroup(() => this.setEditorHidden(false))); + this._register(editorService.onDidVisibleEditorsChange(() => this.setEditorHidden(false))); + this._register(editorGroupService.onDidActivateGroup(() => this.setEditorHidden(false))); // Configuration changes - this._register(this.configurationService.onDidChangeConfiguration(() => this.doUpdateLayoutConfiguration())); + this._register(configurationService.onDidChangeConfiguration(() => this.doUpdateLayoutConfiguration())); // Fullscreen changes this._register(onDidChangeFullscreen(() => this.onFullscreenChanged())); // Group changes - this._register(this.editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.state.editor.centered))); - this._register(this.editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.state.editor.centered))); + this._register(editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.state.editor.centered))); + this._register(editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.state.editor.centered))); // Prevent workbench from scrolling #55456 this._register(addDisposableListener(this.workbench, EventType.SCROLL, () => this.workbench.scrollTop = 0)); // Menubar visibility changes - if ((isWindows || isLinux) && getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') { - this._register(this.titlebarPart.onMenubarVisibilityChange(visible => this.onMenubarToggled(visible))); + if ((isWindows || isLinux) && getTitleBarStyle(configurationService, environmentService) === 'custom') { + this._register(titleService.onMenubarVisibilityChange(visible => this.onMenubarToggled(visible))); } } @@ -1025,6 +1034,9 @@ export class Workbench extends Disposable implements IPartService { const contextService = accessor.get(IWorkspaceContextService); const environmentService = accessor.get(IEnvironmentService); + this.windowService = accessor.get(IWindowService); + this.contextViewService = accessor.get(IContextViewService); + // Fullscreen this.state.fullscreen = isFullscreen(); @@ -1325,6 +1337,7 @@ export class Workbench extends Disposable implements IPartService { if (this.state.zenMode.transitionedToCenteredEditorLayout) { this.centerEditorLayout(false, true); } + setLineNumbers(this.configurationService.getValue('editor.lineNumbers')); // Status bar and activity bar visibility come from settings -> update their visibility. diff --git a/src/vs/workbench/services/editor/common/editorGroupsService.ts b/src/vs/workbench/services/editor/common/editorGroupsService.ts index 948c1ec185c..b4913a3e9d5 100644 --- a/src/vs/workbench/services/editor/common/editorGroupsService.ts +++ b/src/vs/workbench/services/editor/common/editorGroupsService.ts @@ -165,6 +165,11 @@ export interface IEditorGroupsService { */ readonly onDidMoveGroup: Event; + /** + * An event for when a group gets activated. + */ + readonly onDidActivateGroup: Event; + /** * An event for when the group container is layed out. */ diff --git a/src/vs/workbench/services/title/common/titleService.ts b/src/vs/workbench/services/title/common/titleService.ts index e651fae3add..1745a6a2449 100644 --- a/src/vs/workbench/services/title/common/titleService.ts +++ b/src/vs/workbench/services/title/common/titleService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { Event } from 'vs/base/common/event'; export const ITitleService = createDecorator('titleService'); @@ -15,6 +16,11 @@ export interface ITitleProperties { export interface ITitleService { _serviceBrand: any; + /** + * An event when the menubar visibility changes. + */ + readonly onMenubarVisibilityChange: Event; + /** * Update some environmental title properties. */ diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index ccd4fc6df40..1eb218fa51d 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -548,6 +548,7 @@ export class TestEditorGroupsService implements EditorGroupsServiceImpl { constructor(public groups: TestEditorGroup[] = []) { } onDidActiveGroupChange: Event = Event.None; + onDidActivateGroup: Event = Event.None; onDidAddGroup: Event = Event.None; onDidRemoveGroup: Event = Event.None; onDidMoveGroup: Event = Event.None; From 763ae0943dc1639cfc540cdcd0f0ad47dcc1560b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 15:36:56 +0100 Subject: [PATCH 158/172] eng - some extHost strict-null work --- src/vs/workbench/api/electron-browser/mainThreadEditors.ts | 2 +- src/vs/workbench/api/node/extHost.api.impl.ts | 2 +- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostTextEditors.ts | 2 +- src/vs/workbench/api/node/extHostWorkspace.ts | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index d1d7e1cd812..97ff3f6f4a6 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -114,7 +114,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { // --- from extension host process - $tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise { + $tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise { const uri = URI.revive(resource); const editorOptions: ITextEditorOptions = { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 4d2e7c01c30..652f64d8ca2 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -527,7 +527,7 @@ export function createApiFactory( onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) { return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables); }, - asRelativePath: (pathOrUri, includeWorkspace) => { + asRelativePath: (pathOrUri, includeWorkspace?) => { return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace); }, findFiles: (include, exclude, maxResults?, token?) => { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 0d20d99f8e1..6296303e877 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -224,7 +224,7 @@ export interface ITextDocumentShowOptions { } export interface MainThreadTextEditorsShape extends IDisposable { - $tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise; + $tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise; $registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void; $removeTextEditorDecorationType(key: string): void; $tryShowEditor(id: string, position: EditorViewColumn): Promise; diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index a42ec9c245f..ce6b21dcc14 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -75,7 +75,7 @@ export class ExtHostEditors implements ExtHostEditorsShape { } return this._proxy.$tryShowTextDocument(document.uri, options).then(id => { - const editor = this._extHostDocumentsAndEditors.getEditor(id); + const editor = id && this._extHostDocumentsAndEditors.getEditor(id); if (editor) { return editor; } else { diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index bcd01710615..ad7f3b3097a 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -321,10 +321,10 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac return folders[0].uri.fsPath; } - getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string | undefined { + getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string { let resource: URI | undefined; - let path: string | undefined; + let path: string = ''; if (typeof pathOrUri === 'string') { resource = URI.file(pathOrUri); path = pathOrUri; @@ -354,7 +354,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac if (includeWorkspace && folder.name) { result = `${folder.name}/${result}`; } - return result; + return result!; } private trySetWorkspaceFolders(folders: vscode.WorkspaceFolder[]): void { From 672b272fa3e350e9191b444e351e325742b97364 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Mar 2019 17:19:10 +0100 Subject: [PATCH 159/172] dont use super and async/wait... --- .../services/files/node/remoteFileService.ts | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/services/files/node/remoteFileService.ts b/src/vs/workbench/services/files/node/remoteFileService.ts index 36687a83c68..c01f0c214ac 100644 --- a/src/vs/workbench/services/files/node/remoteFileService.ts +++ b/src/vs/workbench/services/files/node/remoteFileService.ts @@ -549,13 +549,13 @@ export class RemoteFileService extends FileService { } } - private async _doMoveWithInScheme(source: URI, target: URI, overwrite: boolean = false): Promise { + private _doMoveWithInScheme(source: URI, target: URI, overwrite: boolean = false): Promise { - if (overwrite) { - await this.del(target, { recursive: true }).catch(_err => { /*ignore*/ }); - } + const prepare = overwrite + ? Promise.resolve(this.del(target, { recursive: true }).catch(_err => { /*ignore*/ })) + : Promise.resolve(); - return this._withProvider(source).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { + return prepare.then(() => this._withProvider(source)).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { return RemoteFileService._mkdirp(provider, resources.dirname(target)).then(() => { return provider.rename(source, target, { overwrite }).then(() => { return this.resolveFile(target); @@ -589,7 +589,7 @@ export class RemoteFileService extends FileService { return super.copyFile(source, target, overwrite); } - return this._withProvider(target).then(RemoteFileService._throwIfFileSystemIsReadonly).then(async provider => { + return this._withProvider(target).then(RemoteFileService._throwIfFileSystemIsReadonly).then(provider => { if (source.scheme === target.scheme && (provider.capabilities & FileSystemProviderCapabilities.FileFolderCopy)) { // good: provider supports copy withing scheme @@ -607,36 +607,37 @@ export class RemoteFileService extends FileService { }); } - if (overwrite) { - await this.del(target, { recursive: true }).catch(_err => { /*ignore*/ }); - } + const prepare = overwrite + ? Promise.resolve(this.del(target, { recursive: true }).catch(_err => { /*ignore*/ })) + : Promise.resolve(); // todo@ben, can only copy text files // https://github.com/Microsoft/vscode/issues/41543 - return this.resolveContent(source, { acceptTextOnly: true }).then(content => { - return this._withProvider(target).then(provider => { - return this._writeFile( - provider, target, - new StringSnapshot(content.value), - content.encoding, - { create: true, overwrite: !!overwrite } - ).then(fileStat => { - this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); - return fileStat; + return prepare.then(() => { + return this.resolveContent(source, { acceptTextOnly: true }).then(content => { + return this._withProvider(target).then(provider => { + return this._writeFile( + provider, target, + new StringSnapshot(content.value), + content.encoding, + { create: true, overwrite: !!overwrite } + ).then(fileStat => { + this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); + return fileStat; + }); + }, err => { + const result = this._tryParseFileOperationResult(err); + if (result === FileOperationResult.FILE_MOVE_CONFLICT) { + throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); + } else if (err instanceof Error && err.name === 'ENOPRO') { + // file scheme + return super.updateContent(target, content.value, { encoding: content.encoding }); + } else { + return Promise.reject(err); + } }); - }, err => { - const result = this._tryParseFileOperationResult(err); - if (result === FileOperationResult.FILE_MOVE_CONFLICT) { - throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); - } else if (err instanceof Error && err.name === 'ENOPRO') { - // file scheme - return super.updateContent(target, content.value, { encoding: content.encoding }); - } else { - return Promise.reject(err); - } }); }); - }); } From 7866a0a97409149880316c16c1c6b8e8a1a40800 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 6 Mar 2019 17:18:03 +0100 Subject: [PATCH 160/172] null checking in debug/common --- src/tsconfig.strictNullChecks.json | 3 +- .../workbench/contrib/debug/common/debug.ts | 18 +-- .../contrib/debug/common/debugModel.ts | 113 ++++++++++-------- .../contrib/debug/common/debugSource.ts | 6 +- .../contrib/debug/common/replModel.ts | 2 +- .../debug/electron-browser/debugSession.ts | 2 +- 6 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 9ececdd3e50..4ac3a4bf562 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -30,7 +30,8 @@ "./vs/workbench/services/progress/**/*.ts", "./vs/workbench/services/preferences/**/*.ts", "./vs/workbench/services/timer/**/*.ts", - "./vs/workbench/contrib/webview/**/*.ts" + "./vs/workbench/contrib/webview/**/*.ts", + "./vs/workbench/contrib/debug/common/**/*.ts", ], "files": [ "./vs/monaco.d.ts", diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index e303532fc05..39fe368818e 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -152,7 +152,7 @@ export interface IDebugSession extends ITreeElement { getLabel(): string; getSourceForUri(modelUri: uri): Source; - getSource(raw: DebugProtocol.Source): Source; + getSource(raw?: DebugProtocol.Source): Source; setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig }): void; rawUpdate(data: IRawModelUpdate): void; @@ -199,7 +199,7 @@ export interface IDebugSession extends ITreeElement { stackTrace(threadId: number, startFrame: number, levels: number): Promise; exceptionInfo(threadId: number): Promise; scopes(frameId: number): Promise; - variables(variablesReference: number, filter: 'indexed' | 'named', start: number, count: number): Promise; + variables(variablesReference: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise; evaluate(expression: string, frameId?: number, context?: string): Promise; customRequest(request: string, args: any): Promise; @@ -214,7 +214,7 @@ export interface IDebugSession extends ITreeElement { terminateThreads(threadIds: number[]): Promise; completions(frameId: number, text: string, position: Position, overwriteBefore: number): Promise; - setVariable(variablesReference: number, name: string, value: string): Promise; + setVariable(variablesReference: number | undefined, name: string, value: string): Promise; loadSource(resource: uri): Promise; getLoadedSources(): Promise; } @@ -284,7 +284,7 @@ export interface IScope extends IExpressionContainer { export interface IStackFrame extends ITreeElement { readonly thread: IThread; readonly name: string; - readonly presentationHint: string; + readonly presentationHint: string | undefined; readonly frameId: number; readonly range: IRange; readonly source: Source; @@ -319,9 +319,9 @@ export interface IBreakpointUpdateData { } export interface IBaseBreakpoint extends IEnablement { - readonly condition: string; - readonly hitCondition: string; - readonly logMessage: string; + readonly condition?: string; + readonly hitCondition?: string; + readonly logMessage?: string; readonly verified: boolean; readonly idFromAdapter: number | undefined; } @@ -330,7 +330,7 @@ export interface IBreakpoint extends IBaseBreakpoint { readonly uri: uri; readonly lineNumber: number; readonly endLineNumber?: number; - readonly column: number; + readonly column?: number; readonly endColumn?: number; readonly message?: string; readonly adapterData: any; @@ -394,7 +394,7 @@ export interface IDebugModel extends ITreeElement { getExceptionBreakpoints(): ReadonlyArray; getWatchExpressions(): ReadonlyArray; - onDidChangeBreakpoints: Event; + onDidChangeBreakpoints: Event; onDidChangeCallStack: Event; onDidChangeWatchExpressions: Event; } diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 91422072397..0f833db72af 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -29,7 +29,7 @@ export class SimpleReplElement implements IReplElement { private id: string, public value: string, public severity: severity, - public sourceData: IReplElementSource, + public sourceData?: IReplElementSource, ) { } toString(): string { @@ -98,19 +98,19 @@ export class ExpressionContainer implements IExpressionContainer { protected children?: Promise; constructor( - protected session: IDebugSession, - private _reference: number, + protected session: IDebugSession | undefined, + private _reference: number | undefined, private id: string, - public namedVariables = 0, - public indexedVariables = 0, - private startOfVariables = 0 + public namedVariables: number | undefined = 0, + public indexedVariables: number | undefined = 0, + private startOfVariables: number | undefined = 0 ) { } - get reference(): number { + get reference(): number | undefined { return this._reference; } - set reference(value: number) { + set reference(value: number | undefined) { this._reference = value; this.children = undefined; // invalidate children cache } @@ -137,17 +137,17 @@ export class ExpressionContainer implements IExpressionContainer { return childrenThenable.then(childrenArray => { // Use a dynamic chunk size based on the number of elements #9774 let chunkSize = ExpressionContainer.BASE_CHUNK_SIZE; - while (this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) { + while (!!this.indexedVariables && this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) { chunkSize *= ExpressionContainer.BASE_CHUNK_SIZE; } - if (this.indexedVariables > chunkSize) { + if (!!this.indexedVariables && this.indexedVariables > chunkSize) { // There are a lot of children, create fake intermediate values that represent chunks #9537 const numberOfChunks = Math.ceil(this.indexedVariables / chunkSize); for (let i = 0; i < numberOfChunks; i++) { - const start = this.startOfVariables + i * chunkSize; + const start = (this.startOfVariables || 0) + i * chunkSize; const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize); - childrenArray.push(new Variable(this.session, this, this.reference, `[${start}..${start + count - 1}]`, '', '', null, count, { kind: 'virtual' }, null, true, start)); + childrenArray.push(new Variable(this.session, this, this.reference, `[${start}..${start + count - 1}]`, '', '', undefined, count, { kind: 'virtual' }, undefined, true, start)); } return childrenArray; @@ -168,16 +168,16 @@ export class ExpressionContainer implements IExpressionContainer { get hasChildren(): boolean { // only variables with reference > 0 have children. - return this.reference > 0; + return !!this.reference && this.reference > 0; } - private fetchVariables(start: number, count: number, filter: 'indexed' | 'named'): Promise { - return this.session.variables(this.reference, filter, start, count).then(response => { + private fetchVariables(start: number | undefined, count: number | undefined, filter: 'indexed' | 'named' | undefined): Promise { + return this.session!.variables(this.reference, filter, start, count).then(response => { return response && response.body && response.body.variables - ? distinct(response.body.variables.filter(v => !!v && isString(v.name)), v => v.name).map( - v => new Variable(this.session, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.presentationHint, v.type)) + ? distinct(response.body.variables.filter(v => !!v && isString(v.name)), (v: DebugProtocol.Variable) => v.name).map((v: DebugProtocol.Variable) => + new Variable(this.session, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.presentationHint, v.type)) : []; - }, (e: Error) => [new Variable(this.session, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, null, false)]); + }, (e: Error) => [new Variable(this.session, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, undefined, false)]); } // The adapter explicitly sents the children count of an expression only if there are lots of children which should be chunked. @@ -204,7 +204,7 @@ export class Expression extends ExpressionContainer implements IExpression { public type: string; constructor(public name: string, id = generateUuid()) { - super(null, 0, id); + super(undefined, 0, id); this.available = false; // name is not set if the expression is just being added // in that case do not set default value to prevent flashing #14499 @@ -230,7 +230,7 @@ export class Expression extends ExpressionContainer implements IExpression { this.reference = response.body.variablesReference; this.namedVariables = response.body.namedVariables; this.indexedVariables = response.body.indexedVariables; - this.type = response.body.type; + this.type = response.body.type || this.type; } }, err => { this.value = err.message; @@ -250,15 +250,15 @@ export class Variable extends ExpressionContainer implements IExpression { public errorMessage: string; constructor( - session: IDebugSession, + session: IDebugSession | undefined, public parent: IExpressionContainer, - reference: number, + reference: number | undefined, public name: string, - public evaluateName: string, + public evaluateName: string | undefined, value: string, - namedVariables: number, - indexedVariables: number, - public presentationHint: DebugProtocol.VariablePresentationHint, + namedVariables: number | undefined, + indexedVariables: number | undefined, + public presentationHint: DebugProtocol.VariablePresentationHint | undefined, public type: string | undefined = undefined, public available = true, startOfVariables = 0 @@ -268,6 +268,10 @@ export class Variable extends ExpressionContainer implements IExpression { } setVariable(value: string): Promise { + if (!this.session) { + return Promise.resolve(undefined); + } + return this.session.setVariable((this.parent).reference, this.name, value).then(response => { if (response && response.body) { this.value = response.body.value; @@ -294,8 +298,8 @@ export class Scope extends ExpressionContainer implements IScope { public name: string, reference: number, public expensive: boolean, - namedVariables: number, - indexedVariables: number, + namedVariables?: number, + indexedVariables?: number, public range?: IRange ) { super(stackFrame.thread.session, reference, `scope:${stackFrame.getId()}:${name}:${index}`, namedVariables, indexedVariables); @@ -315,7 +319,7 @@ export class StackFrame implements IStackFrame { public frameId: number, public source: Source, public name: string, - public presentationHint: string, + public presentationHint: string | undefined, public range: IRange, private index: number ) { @@ -331,7 +335,7 @@ export class StackFrame implements IStackFrame { this.scopes = this.thread.session.scopes(this.frameId).then(response => { return response && response.body && response.body.scopes ? response.body.scopes.map((rs, index) => new Scope(this, index, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables, - rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : null)) : []; + rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined)) : []; }, err => []); } @@ -393,7 +397,6 @@ export class Thread implements IThread { public stopped: boolean; constructor(public session: IDebugSession, public name: string, public threadId: number) { - this.stoppedDetails = null; this.callStack = []; this.staleCallStack = []; this.stopped = false; @@ -465,8 +468,8 @@ export class Thread implements IThread { return new StackFrame(this, rsf.id, source, rsf.name, rsf.presentationHint, new Range( rsf.line, rsf.column, - rsf.endLine, - rsf.endColumn + rsf.endLine || rsf.line, + rsf.endColumn || rsf.column ), startFrame + index); }); }, (err: Error) => { @@ -545,9 +548,9 @@ export class BaseBreakpoint extends Enablement implements IBaseBreakpoint { constructor( enabled: boolean, - public hitCondition: string, - public condition: string, - public logMessage: string, + public hitCondition: string | undefined, + public condition: string | undefined, + public logMessage: string | undefined, id: string ) { super(enabled, id); @@ -594,11 +597,11 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint { constructor( public uri: uri, private _lineNumber: number, - private _column: number, + private _column: number | undefined, enabled: boolean, - condition: string, - hitCondition: string, - logMessage: string, + condition: string | undefined, + hitCondition: string | undefined, + logMessage: string | undefined, private _adapterData: any, private textFileService: ITextFileService, id = generateUuid() @@ -620,7 +623,7 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint { return true; } - get column(): number { + get column(): number | undefined { const data = this.getSessionData(); // Only respect the column if the user explictly set the column to have an inline breakpoint return data && typeof data.column === 'number' && typeof this._column === 'number' ? data.column : this._column; @@ -698,9 +701,9 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak constructor( public name: string, enabled: boolean, - hitCondition: string, - condition: string, - logMessage: string, + hitCondition: string | undefined, + condition: string | undefined, + logMessage: string | undefined, id = generateUuid() ) { super(enabled, hitCondition, condition, logMessage, id); @@ -798,7 +801,7 @@ export class DebugModel implements IDebugModel { this._onDidChangeCallStack.fire(undefined); } - get onDidChangeBreakpoints(): Event { + get onDidChangeBreakpoints(): Event { return this._onDidChangeBreakpoints.event; } @@ -832,7 +835,7 @@ export class DebugModel implements IDebugModel { fetchCallStack(thread: Thread): { topCallStack: Promise, wholeCallStack: Promise } { if (thread.session.capabilities.supportsDelayedStackTraceLoading) { // For improved performance load the first stack frame and then load the rest async. - let topCallStack: Promise; + let topCallStack = Promise.resolve(); const wholeCallStack = new Promise((c, e) => { topCallStack = thread.fetchCallStack(1).then(() => { if (!this.schedulers.has(thread.getId())) { @@ -913,7 +916,7 @@ export class DebugModel implements IDebugModel { } addBreakpoints(uri: uri, rawData: IBreakpointData[], fireEvent = true): IBreakpoint[] { - const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled, rawBp.condition, rawBp.hitCondition, rawBp.logMessage, undefined, this.textFileService, rawBp.id)); + const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, !!rawBp.enabled, rawBp.condition, rawBp.hitCondition, rawBp.logMessage, undefined, this.textFileService, rawBp.id)); newBreakpoints.forEach(bp => bp.setSessionId(this.breakpointsSessionId)); this.breakpoints = this.breakpoints.concat(newBreakpoints); this.breakpointsActivated = true; @@ -979,7 +982,10 @@ export class DebugModel implements IDebugModel { return resources.basenameOrAuthority(first.uri).localeCompare(resources.basenameOrAuthority(second.uri)); } if (first.lineNumber === second.lineNumber) { - return first.column - second.column; + if (first.column && second.column) { + return first.column - second.column; + } + return -1; } return first.lineNumber - second.lineNumber; @@ -1037,7 +1043,7 @@ export class DebugModel implements IDebugModel { removeFunctionBreakpoints(id?: string): void { - let removed: IFunctionBreakpoint[]; + let removed: FunctionBreakpoint[]; if (id) { removed = this.functionBreakpoints.filter(fbp => fbp.getId() === id); this.functionBreakpoints = this.functionBreakpoints.filter(fbp => fbp.getId() !== id); @@ -1075,10 +1081,11 @@ export class DebugModel implements IDebugModel { moveWatchExpression(id: string, position: number): void { const we = this.watchExpressions.filter(we => we.getId() === id).pop(); - this.watchExpressions = this.watchExpressions.filter(we => we.getId() !== id); - this.watchExpressions = this.watchExpressions.slice(0, position).concat(we, this.watchExpressions.slice(position)); - - this._onDidChangeWatchExpressions.fire(undefined); + if (we) { + this.watchExpressions = this.watchExpressions.filter(we => we.getId() !== id); + this.watchExpressions = this.watchExpressions.slice(0, position).concat(we, this.watchExpressions.slice(position)); + this._onDidChangeWatchExpressions.fire(undefined); + } } sourceIsNotAvailable(uri: uri): void { diff --git a/src/vs/workbench/contrib/debug/common/debugSource.ts b/src/vs/workbench/contrib/debug/common/debugSource.ts index 8efc84301ea..d9b9e1d1a6d 100644 --- a/src/vs/workbench/contrib/debug/common/debugSource.ts +++ b/src/vs/workbench/contrib/debug/common/debugSource.ts @@ -33,10 +33,12 @@ export class Source { public readonly uri: uri; public available: boolean; + public raw: DebugProtocol.Source; - constructor(public raw: DebugProtocol.Source, sessionId: string) { + constructor(raw_: DebugProtocol.Source | undefined, sessionId: string) { let path: string; - if (raw) { + if (raw_) { + this.raw = raw_; path = this.raw.path || this.raw.name || ''; this.available = true; } else { diff --git a/src/vs/workbench/contrib/debug/common/replModel.ts b/src/vs/workbench/contrib/debug/common/replModel.ts index c4556ec3eca..e8c1cd2580f 100644 --- a/src/vs/workbench/contrib/debug/common/replModel.ts +++ b/src/vs/workbench/contrib/debug/common/replModel.ts @@ -46,7 +46,7 @@ export class ReplModel { // remove potential empty lines between different repl types this.replElements.pop(); } else if (previousElement instanceof SimpleReplElement && sev === previousElement.severity && toAdd.length && toAdd[0].sourceData === previousElement.sourceData) { - previousElement.value += toAdd.shift().value; + previousElement.value += toAdd.shift()!.value; } this.addReplElements(toAdd); } else { diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts index 3582ba6a3f1..cd82b55507d 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts @@ -785,7 +785,7 @@ export class DebugSession implements IDebugSession { return this.sources.get(this.getUriKey(uri)); } - getSource(raw: DebugProtocol.Source): Source { + getSource(raw?: DebugProtocol.Source): Source { let source = new Source(raw, this.getId()); const uriKey = this.getUriKey(source.uri); const found = this.sources.get(uriKey); From 2f62d285480cd40d66462d8c290c08de73ed5f73 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 6 Mar 2019 17:30:38 +0100 Subject: [PATCH 161/172] debug/terminals.ts strict null checks --- src/tsconfig.strictNullChecks.json | 3 ++- .../workbench/contrib/debug/node/terminals.ts | 19 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 4ac3a4bf562..9ae7f712530 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -517,7 +517,8 @@ "./vs/workbench/test/electron-browser/api/mainThreadDiagnostics.test.ts", "./vs/workbench/test/electron-browser/api/mainThreadDocumentContentProviders.test.ts", "./vs/workbench/test/electron-browser/api/mock.ts", - "./vs/workbench/test/electron-browser/api/testRPCProtocol.ts" + "./vs/workbench/test/electron-browser/api/testRPCProtocol.ts", + "./vs/workbench/contrib/debug/node/terminals.ts" ], "exclude": [ "./typings/require-monaco.d.ts", diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index f399b6bb8d9..3bb371f4b5b 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -33,7 +33,7 @@ export function getDefaultTerminalLinuxReady(): Promise { if (!_DEFAULT_TERMINAL_LINUX_READY) { _DEFAULT_TERMINAL_LINUX_READY = new Promise(c => { if (env.isLinux) { - Promise.all([pfs.exists('/etc/debian_version'), process.lazyEnv]).then(([isDebian]) => { + Promise.all([pfs.exists('/etc/debian_version'), process.lazyEnv]).then(([isDebian]) => { if (isDebian) { c('x-terminal-emulator'); } else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') { @@ -67,19 +67,18 @@ export function getDefaultTerminalWindows(): string { } abstract class TerminalLauncher implements ITerminalLauncher { - public runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise { - return this.runInTerminal0(args.title, args.cwd, args.args, args.env || {}, config); - } - runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, config): Promise { - return undefined; + runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise { + return this.runInTerminal0(args.title!, args.cwd, args.args, args.env || {}, config); } + + abstract runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment | {}, config): Promise; } class WinTerminalService extends TerminalLauncher { private static readonly CMD = 'cmd.exe'; - public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { + runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { const exec = configuration.external.windowsExec || getDefaultTerminalWindows(); @@ -117,7 +116,7 @@ class MacTerminalService extends TerminalLauncher { private static readonly DEFAULT_TERMINAL_OSX = 'Terminal.app'; private static readonly OSASCRIPT = '/usr/bin/osascript'; // osascript is the AppleScript interpreter on OS X - public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { + runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { const terminalApp = configuration.external.osxExec || MacTerminalService.DEFAULT_TERMINAL_OSX; @@ -184,7 +183,7 @@ class LinuxTerminalService extends TerminalLauncher { private static readonly WAIT_MESSAGE = nls.localize('press.any.key', "Press any key to continue..."); - public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { + runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise { const terminalConfig = configuration.external; const execThenable: Promise = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : getDefaultTerminalLinuxReady(); @@ -348,7 +347,7 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments } } if (args.args && args.args.length > 0) { - const cmd = quote(args.args.shift()); + const cmd = quote(args.args.shift()!); command += (cmd[0] === '\'') ? `& ${cmd} ` : `${cmd} `; for (let a of args.args) { command += `${quote(a)} `; From 84b046ce10eb3fc3e1afcf4a227f53c79a3549d5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 6 Mar 2019 18:33:11 +0100 Subject: [PATCH 162/172] debt - introduce ILayoutService This allows to declare more services declaratively. --- .../standalone/browser/simpleServices.ts | 16 ++++ .../standalone/browser/standaloneServices.ts | 7 +- .../contextview/browser/contextViewService.ts | 7 +- .../platform/layout/browser/layoutService.ts | 30 ++++++ src/vs/workbench/browser/legacyLayout.ts | 18 ---- .../browser/parts/quickinput/quickInput.ts | 14 ++- .../parts/quickopen/quickOpenController.ts | 16 ++-- .../workbench/electron-browser/workbench.ts | 94 +++++++------------ .../services/history/browser/history.ts | 3 + src/vs/workbench/workbench.main.ts | 3 + 10 files changed, 113 insertions(+), 95 deletions(-) create mode 100644 src/vs/platform/layout/browser/layoutService.ts diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index c76b38b22df..ab55ea98971 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -43,6 +43,7 @@ import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; +import { ILayoutService, IDimension } from 'vs/platform/layout/browser/layoutService'; export class SimpleModel implements IResolvedTextEditorModel { @@ -671,3 +672,18 @@ export class SimpleUriLabelService implements ILabelService { return ''; } } + +export class SimpleLayoutService implements ILayoutService { + _serviceBrand: any; + + public onLayout = Event.None; + + private _dimension: IDimension; + get dimension(): IDimension { + if (!this._dimension) { + this._dimension = dom.getClientArea(window.document.body); + } + + return this._dimension; + } +} diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index df278c89b82..1d0568208d0 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -13,7 +13,7 @@ import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; -import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, BrowserAccessibilityService } from 'vs/editor/standalone/browser/simpleServices'; +import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, BrowserAccessibilityService, SimpleLayoutService } from 'vs/editor/standalone/browser/simpleServices'; import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl'; import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; @@ -46,6 +46,7 @@ import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDeco import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl'; import { ISuggestMemoryService, SuggestMemoryService } from 'vs/editor/contrib/suggest/suggestMemory'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; export interface IEditorOverrideServices { [index: string]: any; @@ -196,7 +197,9 @@ export class DynamicStandaloneServices extends Disposable { let keybindingService = ensure(IKeybindingService, () => this._register(new StandaloneKeybindingService(contextKeyService, commandService, telemetryService, notificationService, domElement))); - let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(domElement, telemetryService, new NullLogService()))); + let layoutService = ensure(ILayoutService, () => new SimpleLayoutService()); + + let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(domElement, telemetryService, new NullLogService(), layoutService))); ensure(IContextMenuService, () => this._register(new ContextMenuService(domElement, telemetryService, notificationService, contextViewService, keybindingService, themeService))); diff --git a/src/vs/platform/contextview/browser/contextViewService.ts b/src/vs/platform/contextview/browser/contextViewService.ts index 48b0f51eb86..0bcada24ea8 100644 --- a/src/vs/platform/contextview/browser/contextViewService.ts +++ b/src/vs/platform/contextview/browser/contextViewService.ts @@ -8,6 +8,7 @@ import { ContextView } from 'vs/base/browser/ui/contextview/contextview'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILogService } from 'vs/platform/log/common/log'; import { Disposable } from 'vs/base/common/lifecycle'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; export class ContextViewService extends Disposable implements IContextViewService { _serviceBrand: any; @@ -17,11 +18,15 @@ export class ContextViewService extends Disposable implements IContextViewServic constructor( container: HTMLElement, @ITelemetryService telemetryService: ITelemetryService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @ILayoutService readonly layoutService: ILayoutService ) { super(); this.contextView = this._register(new ContextView(container)); + this.layout(); + + this._register(layoutService.onLayout(() => this.layout())); } // ContextView diff --git a/src/vs/platform/layout/browser/layoutService.ts b/src/vs/platform/layout/browser/layoutService.ts new file mode 100644 index 00000000000..d9cc51f1a2d --- /dev/null +++ b/src/vs/platform/layout/browser/layoutService.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const ILayoutService = createDecorator('layoutService'); + +export interface IDimension { + width: number; + height: number; +} + +export interface ILayoutService { + + _serviceBrand: any; + + /** + * The dimensions of the container. + */ + readonly dimension: IDimension; + + /** + * An event that is emitted when the container is layed out. The + * event carries the dimensions of the container as part of it. + */ + readonly onLayout: Event; +} \ No newline at end of file diff --git a/src/vs/workbench/browser/legacyLayout.ts b/src/vs/workbench/browser/legacyLayout.ts index e47480d7e9f..24b179fe2ad 100644 --- a/src/vs/workbench/browser/legacyLayout.ts +++ b/src/vs/workbench/browser/legacyLayout.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; -import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput'; import { Sash, ISashEvent, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation } from 'vs/base/browser/ui/sash/sash'; import { IPartService, Position, ILayoutOptions, Parts } from 'vs/workbench/services/part/common/partService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -14,8 +12,6 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { isMacintosh } from 'vs/base/common/platform'; import { memoize } from 'vs/base/common/decorators'; -import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter'; -import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts'; import { Dimension, getClientArea, size, position, hide, show } from 'vs/base/browser/dom'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; @@ -78,10 +74,6 @@ export class WorkbenchLegacyLayout extends Disposable implements IVerticalSashLa panel: PanelPart, statusbar: StatusbarPart }, - private quickopen: QuickOpenController, - private quickInput: QuickInputService, - private notificationsCenter: NotificationsCenter, - private notificationsToasts: NotificationsToasts, @IStorageService private readonly storageService: IStorageService, @IContextViewService private readonly contextViewService: IContextViewService, @IPartService private readonly partService: IPartService, @@ -626,16 +618,6 @@ export class WorkbenchLegacyLayout extends Disposable implements IVerticalSashLa show(statusbarContainer); } - // Quick open - this.quickopen.layout(this.workbenchSize); - - // Quick input - this.quickInput.layout(this.workbenchSize); - - // Notifications - this.notificationsCenter.layout(this.workbenchSize); - this.notificationsToasts.layout(this.workbenchSize); - // Sashes this.sashXOne.layout(); if (panelPosition === Position.BOTTOM) { diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.ts b/src/vs/workbench/browser/parts/quickinput/quickInput.ts index 8860f8046b7..7fa1be9a216 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInput.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.ts @@ -43,6 +43,8 @@ import { getIconClass } from 'vs/workbench/browser/parts/quickinput/quickInputUt import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; const $ = dom.$; @@ -816,7 +818,6 @@ export class QuickInputService extends Component implements IQuickInputService { private static readonly MAX_WIDTH = 600; // Max total width of quick open widget private idPrefix = 'quickInput_'; // Constant since there is still only one. - private layoutDimensions: dom.Dimension; private titleBar: HTMLElement; private filterContainer: HTMLElement; private visibleCountContainer: HTMLElement; @@ -846,12 +847,14 @@ export class QuickInputService extends Component implements IQuickInputService { @IContextKeyService private readonly contextKeyService: IContextKeyService, @IThemeService themeService: IThemeService, @IStorageService storageService: IStorageService, - @IAccessibilityService private readonly accessibilityService: IAccessibilityService + @IAccessibilityService private readonly accessibilityService: IAccessibilityService, + @ILayoutService private readonly layoutService: ILayoutService ) { super(QuickInputService.ID, themeService, storageService); this.inQuickOpenContext = InQuickOpenContextKey.bindTo(contextKeyService); this._register(this.quickOpenService.onShow(() => this.inQuickOpen('quickOpen', true))); this._register(this.quickOpenService.onHide(() => this.inQuickOpen('quickOpen', false))); + this._register(this.layoutService.onLayout(dimension => this.layout(dimension))); this.registerKeyModsListeners(); } @@ -1400,17 +1403,16 @@ export class QuickInputService extends Component implements IQuickInputService { } layout(dimension: dom.Dimension): void { - this.layoutDimensions = dimension; this.updateLayout(); } private updateLayout() { - if (this.layoutDimensions && this.ui) { + if (this.ui) { const titlebarOffset = this.partService.getTitleBarOffset(); this.ui.container.style.top = `${titlebarOffset}px`; const style = this.ui.container.style; - const width = Math.min(this.layoutDimensions.width * 0.62 /* golden cut */, QuickInputService.MAX_WIDTH); + const width = Math.min(this.layoutService.dimension.width * 0.62 /* golden cut */, QuickInputService.MAX_WIDTH); style.width = width + 'px'; style.marginLeft = '-' + (width / 2) + 'px'; @@ -1467,3 +1469,5 @@ export class BackAction extends Action { return Promise.resolve(); } } + +registerSingleton(IQuickInputService, QuickInputService, true); \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 3eb74651206..0e4c31da45f 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -50,6 +50,8 @@ import { timeout } from 'vs/base/common/async'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; import { IStorageService } from 'vs/platform/storage/common/storage'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; const HELP_PREFIX = '?'; @@ -73,7 +75,6 @@ export class QuickOpenController extends Component implements IQuickOpenService private lastInputValue: string; private lastSubmittedInputValue: string; private quickOpenWidget: QuickOpenWidget; - private dimension: Dimension; private mapResolvedHandlersToPrefix: { [prefix: string]: Promise; } = Object.create(null); private mapContextKeyToContext: { [id: string]: IContextKey; } = Object.create(null); private handlerOnOpenCalled: { [prefix: string]: boolean; } = Object.create(null); @@ -94,7 +95,8 @@ export class QuickOpenController extends Component implements IQuickOpenService @IPartService private readonly partService: IPartService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @IThemeService themeService: IThemeService, - @IStorageService storageService: IStorageService + @IStorageService storageService: IStorageService, + @ILayoutService private readonly layoutService: ILayoutService ) { super(QuickOpenController.ID, themeService, storageService); @@ -109,6 +111,7 @@ export class QuickOpenController extends Component implements IQuickOpenService this._register(this.configurationService.onDidChangeConfiguration(() => this.updateConfiguration())); this._register(this.partService.onTitleBarVisibilityChange(() => this.positionQuickOpenWidget())); this._register(browser.onDidChangeZoomLevel(() => this.positionQuickOpenWidget())); + this._register(this.layoutService.onLayout(dimension => this.layout(dimension))); } private updateConfiguration(): void { @@ -195,9 +198,7 @@ export class QuickOpenController extends Component implements IQuickOpenService } // Layout - if (this.dimension) { - this.quickOpenWidget.layout(this.dimension); - } + this.quickOpenWidget.layout(this.layoutService.dimension); // Show quick open with prefix or editor history if (!this.quickOpenWidget.isVisible() || quickNavigateConfiguration) { @@ -624,9 +625,8 @@ export class QuickOpenController extends Component implements IQuickOpenService } layout(dimension: Dimension): void { - this.dimension = dimension; if (this.quickOpenWidget) { - this.quickOpenWidget.layout(this.dimension); + this.quickOpenWidget.layout(dimension); } } } @@ -863,3 +863,5 @@ export class RemoveFromEditorHistoryAction extends Action { }); } } + +registerSingleton(IQuickOpenService, QuickOpenController, true); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 923b1bd1575..a28f951ca61 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -29,9 +29,6 @@ import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; import { ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet'; -import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; -import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput'; import { getServices } from 'vs/platform/instantiation/common/extensions'; import { Position, Parts, IPartService, ILayoutOptions } from 'vs/workbench/services/part/common/partService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; @@ -46,9 +43,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IFileService } from 'vs/platform/files/common/files'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ITitleService } from 'vs/workbench/services/title/common/titleService'; -import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { LifecyclePhase, StartupKind, ILifecycleService, WillShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle'; @@ -97,12 +92,11 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; -import { HistoryService } from 'vs/workbench/services/history/browser/history'; import { WorkbenchThemeService } from 'vs/workbench/services/themes/browser/workbenchThemeService'; import { IProductService } from 'vs/platform/product/common/product'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; -import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { ILayoutService, IDimension } from 'vs/platform/layout/browser/layoutService'; // import@node import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc'; @@ -203,12 +197,6 @@ export class Workbench extends Disposable implements IPartService { private editorPart: EditorPart; private statusbarPart: StatusbarPart; - private quickOpen: QuickOpenController; - private quickInput: QuickInputService; - - private notificationsCenter: NotificationsCenter; - private notificationsToasts: NotificationsToasts; - constructor( private container: HTMLElement, private configuration: IWindowConfiguration, @@ -358,6 +346,7 @@ export class Workbench extends Disposable implements IPartService { // Parts serviceCollection.set(IPartService, this); // TODO@Ben use SyncDescriptor + serviceCollection.set(ILayoutService, this); // TODO@Ben use SyncDescriptor // Labels serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true)); @@ -502,17 +491,6 @@ export class Workbench extends Disposable implements IPartService { this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART); serviceCollection.set(ITitleService, this.titlebarPart); // TODO@Ben use SyncDescriptor - // History - serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService)); - - // Quick open service (quick open controller) - this.quickOpen = this.instantiationService.createInstance(QuickOpenController); - serviceCollection.set(IQuickOpenService, this.quickOpen); // TODO@Ben use SyncDescriptor - - // Quick input service - this.quickInput = this.instantiationService.createInstance(QuickInputService); - serviceCollection.set(IQuickInputService, this.quickInput); // TODO@Ben use SyncDescriptor - // Contributed services const contributedServices = getServices(); for (let contributedService of contributedServices) { @@ -692,30 +670,26 @@ export class Workbench extends Disposable implements IPartService { private createNotificationsHandlers(accessor: ServicesAccessor): void { const notificationService = accessor.get(INotificationService) as NotificationService; - // Notifications Center - this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, notificationService.model)); - - // Notifications Toasts - this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, notificationService.model)); - - // Notifications Alerts + // Instantiate Notification components + const notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, notificationService.model)); + const notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, notificationService.model)); this._register(this.instantiationService.createInstance(NotificationsAlerts, notificationService.model)); - - // Notifications Status const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, notificationService.model); - // Eventing - this._register(this.notificationsCenter.onDidChangeVisibility(() => { + // Visibility + this._register(notificationsCenter.onDidChangeVisibility(() => { + notificationsStatus.update(notificationsCenter.isVisible); + notificationsToasts.update(notificationsCenter.isVisible); + })); - // Update status - notificationsStatus.update(this.notificationsCenter.isVisible); - - // Update toasts - this.notificationsToasts.update(this.notificationsCenter.isVisible); + // Layout + this._register(this.onLayout(dimension => { + notificationsCenter.layout(dimension); + notificationsToasts.layout(dimension); })); // Register Commands - registerNotificationCommands(this.notificationsCenter, this.notificationsToasts); + registerNotificationCommands(notificationsCenter, notificationsToasts); } private restoreWorkbench(): Promise { @@ -828,6 +802,12 @@ export class Workbench extends Disposable implements IPartService { private readonly _onZenMode: Emitter = this._register(new Emitter()); get onZenModeChange(): Event { return this._onZenMode.event; } + private readonly _onLayout = this._register(new Emitter()); + get onLayout(): Event { return this._onLayout.event; } + + private _dimension: IDimension; + get dimension(): IDimension { return this._dimension; } + private workbenchGrid: Grid | WorkbenchLegacyLayout; private titleBarPartView: View; @@ -837,7 +817,6 @@ export class Workbench extends Disposable implements IPartService { private editorPartView: View; private statusBarPartView: View; - private contextViewService: IContextViewService; private windowService: IWindowService; private readonly state = { @@ -1035,7 +1014,6 @@ export class Workbench extends Disposable implements IPartService { const environmentService = accessor.get(IEnvironmentService); this.windowService = accessor.get(IWindowService); - this.contextViewService = accessor.get(IContextViewService); // Fullscreen this.state.fullscreen = isFullscreen(); @@ -1406,38 +1384,30 @@ export class Workbench extends Disposable implements IPartService { sidebar: this.sidebarPart, panel: this.panelPart, statusbar: this.statusbarPart, - }, - this.quickOpen, - this.quickInput, - this.notificationsCenter, - this.notificationsToasts + } ); } } layout(options?: ILayoutOptions): void { - this.contextViewService.layout(); - if (!this.disposed) { + this._dimension = getClientArea(this.container); + if (this.workbenchGrid instanceof Grid) { - const dimensions = getClientArea(this.container); position(this.workbench, 0, 0, 0, 0, 'relative'); - size(this.workbench, dimensions.width, dimensions.height); + size(this.workbench, this._dimension.width, this._dimension.height); - // Layout the grid - this.workbenchGrid.layout(dimensions.width, dimensions.height); + // Layout the grid widget + this.workbenchGrid.layout(this._dimension.width, this._dimension.height); - // Layout non-view ui components - this.quickInput.layout(dimensions); - this.quickOpen.layout(dimensions); - this.notificationsCenter.layout(dimensions); - this.notificationsToasts.layout(dimensions); - - // Layout Grid + // Layout grid views this.layoutGrid(); } else { this.workbenchGrid.layout(options); } + + // Emit as event + this._onLayout.fire(this._dimension); } } diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 7f52cda2121..11c83492a74 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -30,6 +30,7 @@ import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { coalesce } from 'vs/base/common/arrays'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; /** * Stores the selection & view state of an editor and allows to compare it to other selection states. @@ -971,3 +972,5 @@ export class HistoryService extends Disposable implements IHistoryService { return undefined; } } + +registerSingleton(IHistoryService, HistoryService); \ No newline at end of file diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index e06ec70c0b0..d8bf039ff5d 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -74,6 +74,9 @@ import 'vs/workbench/services/textmodelResolver/common/textModelResolverService' import 'vs/workbench/services/textfile/common/textFileService'; import 'vs/workbench/services/dialogs/electron-browser/dialogService'; import 'vs/workbench/services/backup/node/backupFileService'; +import 'vs/workbench/services/history/browser/history'; +import 'vs/workbench/browser/parts/quickinput/quickInput'; +import 'vs/workbench/browser/parts/quickopen/quickOpenController'; registerSingleton(IMenuService, MenuService, true); registerSingleton(IListService, ListService, true); From b91adad1cfd8a75ebce9752878da177d1ac50cdc Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 6 Mar 2019 18:44:24 +0100 Subject: [PATCH 163/172] Fix file ordering issue in simple file picker --- .../services/dialogs/electron-browser/remoteFileDialog.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts index 08f9ea471b8..1861f1c0bdf 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts @@ -468,7 +468,9 @@ export class RemoteFileDialog { if (i1.isFolder !== i2.isFolder) { return i1.isFolder ? -1 : 1; } - return i1.label.localeCompare(i2.label); + const trimmed1 = this.endsWithSlash(i1.label) ? i1.label.substr(0, i1.label.length - 1) : i1.label; + const trimmed2 = this.endsWithSlash(i2.label) ? i2.label.substr(0, i2.label.length - 1) : i2.label; + return trimmed1.localeCompare(trimmed2); }); if (backDir) { From 9a72cf08e47ec97abc1b9b5eae6f359888c73c44 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 6 Mar 2019 18:45:22 +0100 Subject: [PATCH 164/172] null checking in debugger.ts --- src/tsconfig.strictNullChecks.json | 1 + .../workbench/contrib/debug/common/debug.ts | 4 +- .../contrib/debug/node/debugAdapter.ts | 32 +++++++------ .../workbench/contrib/debug/node/debugger.ts | 48 +++++++++++-------- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 9ae7f712530..47698340041 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -243,6 +243,7 @@ "./vs/workbench/contrib/debug/common/debugViewModel.ts", "./vs/workbench/contrib/debug/electron-browser/rawDebugSession.ts", "./vs/workbench/contrib/debug/node/debugAdapter.ts", + "./vs/workbench/contrib/debug/node/debugger.ts", "./vs/workbench/contrib/debug/node/telemetryApp.ts", "./vs/workbench/contrib/debug/test/common/debugSource.test.ts", "./vs/workbench/contrib/debug/test/common/debugUtils.test.ts", diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 39fe368818e..000458a22fc 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -112,7 +112,7 @@ export interface IExpression extends IReplElement, IExpressionContainer { export interface IDebugger { createDebugAdapter(session: IDebugSession, outputService: IOutputService): Promise; runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise; - getCustomTelemetryService(): Promise; + getCustomTelemetryService(): Promise; } export const enum State { @@ -516,7 +516,7 @@ export interface IPlatformSpecificAdapterContribution { } export interface IDebuggerContribution extends IPlatformSpecificAdapterContribution { - type?: string; + type: string; label?: string; // debug adapter executable adapterExecutableCommand?: string; diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index 1f0a6b7e6dc..2f3845662d4 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -435,33 +435,35 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { } } - private static extract(contribution: IDebuggerContribution, extensionFolderPath: string): IDebuggerContribution | undefined { - if (!contribution) { + private static extract(platformContribution: IPlatformSpecificAdapterContribution, extensionFolderPath: string): IDebuggerContribution | undefined { + if (!platformContribution) { return undefined; } const result: IDebuggerContribution = Object.create(null); - if (contribution.runtime) { - if (contribution.runtime.indexOf('./') === 0) { // TODO - result.runtime = path.join(extensionFolderPath, contribution.runtime); + if (platformContribution.runtime) { + if (platformContribution.runtime.indexOf('./') === 0) { // TODO + result.runtime = path.join(extensionFolderPath, platformContribution.runtime); } else { - result.runtime = contribution.runtime; + result.runtime = platformContribution.runtime; } } - if (contribution.runtimeArgs) { - result.runtimeArgs = contribution.runtimeArgs; + if (platformContribution.runtimeArgs) { + result.runtimeArgs = platformContribution.runtimeArgs; } - if (contribution.program) { - if (!path.isAbsolute(contribution.program)) { - result.program = path.join(extensionFolderPath, contribution.program); + if (platformContribution.program) { + if (!path.isAbsolute(platformContribution.program)) { + result.program = path.join(extensionFolderPath, platformContribution.program); } else { - result.program = contribution.program; + result.program = platformContribution.program; } } - if (contribution.args) { - result.args = contribution.args; + if (platformContribution.args) { + result.args = platformContribution.args; } + const contribution = platformContribution as IDebuggerContribution; + if (contribution.win) { result.win = ExecutableDebugAdapter.extract(contribution.win, extensionFolderPath); } @@ -490,7 +492,7 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { const debuggers = ed.contributes['debuggers']; if (debuggers && debuggers.length > 0) { debuggers.filter(dbg => typeof dbg.type === 'string' && strings.equalsIgnoreCase(dbg.type, debugType)).forEach(dbg => { - // extract relevant attributes and make then absolute where needed + // extract relevant attributes and make them absolute where needed const extractedDbg = ExecutableDebugAdapter.extract(dbg, ed.extensionLocation.fsPath); // merge diff --git a/src/vs/workbench/contrib/debug/node/debugger.ts b/src/vs/workbench/contrib/debug/node/debugger.ts index a8072f51aab..0b858507e55 100644 --- a/src/vs/workbench/contrib/debug/node/debugger.ts +++ b/src/vs/workbench/contrib/debug/node/debugger.ts @@ -31,7 +31,7 @@ import { isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/de export class Debugger implements IDebugger { - private debuggerContribution: IDebuggerContribution = {}; + private debuggerContribution: IDebuggerContribution; private mergedExtensionDescriptions: IExtensionDescription[] = []; private mainExtensionDescription: IExtensionDescription | undefined; @@ -42,6 +42,7 @@ export class Debugger implements IDebugger { @IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService, @ITelemetryService private readonly telemetryService: ITelemetryService, ) { + this.debuggerContribution = { type: dbgContribution.type }; this.merge(dbgContribution, extensionDescription); } @@ -149,12 +150,15 @@ export class Debugger implements IDebugger { if (this.debuggerContribution.adapterExecutableCommand) { console.info('debugAdapterExecutable attribute in package.json is deprecated and support for it will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.'); const rootFolder = session.root ? session.root.uri.toString() : undefined; - return this.commandService.executeCommand(this.debuggerContribution.adapterExecutableCommand, rootFolder).then((ae: { command: string, args: string[] }) => { - return { - type: 'executable', - command: ae.command, - args: ae.args || [] - }; + return this.commandService.executeCommand(this.debuggerContribution.adapterExecutableCommand, rootFolder).then(ae => { + if (ae) { + return { + type: 'executable', + command: ae.command, + args: ae.args || [] + }; + } + throw new Error('command adapterExecutableCommand did not return proper command.'); }); } @@ -197,15 +201,15 @@ export class Debugger implements IDebugger { return this.debuggerContribution.type; } - get variables(): { [key: string]: string } { + get variables(): { [key: string]: string } | undefined { return this.debuggerContribution.variables; } - get configurationSnippets(): IJSONSchemaSnippet[] { + get configurationSnippets(): IJSONSchemaSnippet[] | undefined { return this.debuggerContribution.configurationSnippets; } - get languages(): string[] { + get languages(): string[] | undefined { return this.debuggerContribution.languages; } @@ -254,8 +258,11 @@ export class Debugger implements IDebugger { } @memoize - getCustomTelemetryService(): Promise { - if (!this.debuggerContribution.aiKey) { + getCustomTelemetryService(): Promise { + + const aiKey = this.debuggerContribution.aiKey; + + if (!aiKey) { return Promise.resolve(undefined); } @@ -270,7 +277,7 @@ export class Debugger implements IDebugger { { serverName: 'Debug Telemetry', timeout: 1000 * 60 * 5, - args: [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), this.debuggerContribution.aiKey], + args: [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey], env: { ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', @@ -286,10 +293,12 @@ export class Debugger implements IDebugger { }); } - getSchemaAttributes(): IJSONSchema[] { + getSchemaAttributes(): IJSONSchema[] | null { + if (!this.debuggerContribution.configurationAttributes) { return null; } + // fill in the default configuration attributes shared by all adapters. const taskSchema = TaskDefinitionRegistry.getJsonSchema(); return Object.keys(this.debuggerContribution.configurationAttributes).map(request => { @@ -339,9 +348,9 @@ export class Debugger implements IDebugger { }; properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA; // Clear out windows, linux and osx fields to not have cycles inside the properties object - properties['windows'] = undefined; - properties['osx'] = undefined; - properties['linux'] = undefined; + delete properties['windows']; + delete properties['osx']; + delete properties['linux']; const osProperties = objects.deepClone(properties); properties['windows'] = { @@ -359,11 +368,10 @@ export class Debugger implements IDebugger { description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."), properties: osProperties }; - Object.keys(attributes.properties).forEach(name => { + Object.keys(properties).forEach(name => { // Use schema allOf property to get independent error reporting #21113 - ConfigurationResolverUtils.applyDeprecatedVariableMessage(attributes.properties[name]); + ConfigurationResolverUtils.applyDeprecatedVariableMessage(properties[name]); }); - return attributes; }); } From 6784a0bd27f8982b3bd539585f997206dbf6f7c1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 6 Mar 2019 10:15:31 -0800 Subject: [PATCH 165/172] Strict null check settings files --- src/tsconfig.strictNullChecks.json | 2 + .../preferences/browser/settingsTree.ts | 55 ++++----- .../preferences/browser/settingsTreeModels.ts | 24 ++-- .../contrib/preferences/browser/tocTree.ts | 10 +- .../electron-browser/settingsEditor2.ts | 109 +++++++++++------- 5 files changed, 115 insertions(+), 85 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 47698340041..6ac1d410616 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -32,6 +32,8 @@ "./vs/workbench/services/timer/**/*.ts", "./vs/workbench/contrib/webview/**/*.ts", "./vs/workbench/contrib/debug/common/**/*.ts", + "./vs/workbench/contrib/preferences/common/**/*.ts", + "./vs/workbench/contrib/preferences/**/settings*.ts", ], "files": [ "./vs/monaco.d.ts", diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 8f1fabdf359..8211f695bbc 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -112,7 +112,7 @@ function _resolveSettingsTree(tocData: ITOCEntry, allSettings: Set): I } if (!children && !settings) { - return null; + throw new Error(`TOC node has no child groups or settings: ${tocData.id}`); } return { @@ -439,7 +439,7 @@ export abstract class AbstractSettingRenderer implements ITreeRenderer this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context.valueType }); + const onChange = value => this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context!.valueType }); template.deprecationWarningElement.innerText = element.setting.deprecationMessage || ''; this.renderValue(element, template, onChange); @@ -488,7 +488,7 @@ export abstract class AbstractSettingRenderer implements ITreeRenderertemplate.controlElement.firstElementChild) { itemElement.setAttribute('role', 'combobox'); label += modifiedText; } @@ -587,7 +587,7 @@ export class SettingNewExtensionsRenderer implements ITreeRenderer { if (template.context) { @@ -621,9 +621,9 @@ export class SettingComplexRenderer extends AbstractSettingRenderer implements I renderTemplate(container: HTMLElement): ISettingComplexItemTemplate { const common = this.renderCommonTemplate(null, container, 'complex'); - const openSettingsButton = new Button(common.controlElement, { title: true, buttonBackground: null, buttonHoverBackground: null }); + const openSettingsButton = new Button(common.controlElement, { title: true, buttonBackground: undefined, buttonHoverBackground: undefined }); common.toDispose.push(openSettingsButton); - common.toDispose.push(openSettingsButton.onDidClick(() => template.onChange(null))); + common.toDispose.push(openSettingsButton.onDidClick(() => template.onChange!())); openSettingsButton.label = localize('editInSettingsJson', "Edit in settings.json"); openSettingsButton.element.classList.add('edit-in-settings-button'); @@ -770,7 +770,7 @@ export class SettingTextRenderer extends AbstractSettingRenderer implements ITre protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingTextItemTemplate, onChange: (value: string) => void): void { const label = this.setElementAriaLabels(dataElement, SETTINGS_TEXT_TEMPLATE_ID, template); - template.onChange = null; + template.onChange = undefined; template.inputBox.value = dataElement.value; template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(value); }; @@ -784,7 +784,7 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre renderTemplate(container: HTMLElement): ISettingEnumItemTemplate { const common = this.renderCommonTemplate(null, container, 'enum'); - const selectBox = new SelectBox([], undefined, this._contextViewService, undefined, { useCustomDrawn: true }); + const selectBox = new SelectBox([], 0, this._contextViewService, undefined, { useCustomDrawn: true }); common.toDispose.push(selectBox); common.toDispose.push(attachSelectBoxStyler(selectBox, this._themeService, { @@ -827,7 +827,7 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre const enumDescriptions = dataElement.setting.enumDescriptions; const enumDescriptionsAreMarkdown = dataElement.setting.enumDescriptionsAreMarkdown; - const displayOptions = dataElement.setting.enum + const displayOptions = dataElement.setting.enum! .map(String) .map(escapeInvisibleChars) .map((data, index) => { @@ -842,10 +842,10 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre const label = this.setElementAriaLabels(dataElement, SETTINGS_ENUM_TEMPLATE_ID, template); template.selectBox.setAriaLabel(label); - const idx = dataElement.setting.enum.indexOf(dataElement.value); - template.onChange = null; + const idx = dataElement.setting.enum!.indexOf(dataElement.value); + template.onChange = undefined; template.selectBox.select(idx); - template.onChange = idx => onChange(dataElement.setting.enum[idx]); + template.onChange = idx => onChange(dataElement.setting.enum![idx]); template.enumDescriptionElement.innerHTML = ''; } @@ -889,7 +889,7 @@ export class SettingNumberRenderer extends AbstractSettingRenderer implements IT super.renderSettingElement(element, index, templateData); } - protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingNumberItemTemplate, onChange: (value: number) => void): void { + protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingNumberItemTemplate, onChange: (value: number | null) => void): void { const numParseFn = (dataElement.valueType === 'integer' || dataElement.valueType === 'nullable-integer') ? parseInt : parseFloat; @@ -898,9 +898,12 @@ export class SettingNumberRenderer extends AbstractSettingRenderer implements IT const label = this.setElementAriaLabels(dataElement, SETTINGS_NUMBER_TEMPLATE_ID, template); - template.onChange = null; + template.onChange = undefined; template.inputBox.value = dataElement.value; - template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(nullNumParseFn(value)); }; + template.onChange = value => { + renderValidations(dataElement, template, false, label); + onChange(nullNumParseFn(value)); + }; renderValidations(dataElement, template, true, label); } @@ -930,7 +933,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message')); const toDispose: IDisposable[] = []; - const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: null }); + const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: undefined }); controlElement.appendChild(checkbox.domNode); toDispose.push(checkbox); toDispose.push(checkbox.onChange(() => { @@ -949,7 +952,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre // Toggle target checkbox if (targetElement.tagName.toLowerCase() !== 'a' && targetId === template.checkbox.domNode.id) { template.checkbox.checked = template.checkbox.checked ? false : true; - template.onChange(checkbox.checked); + template.onChange!(checkbox.checked); } DOM.EventHelper.stop(e); })); @@ -993,7 +996,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre } protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingBoolItemTemplate, onChange: (value: boolean) => void): void { - template.onChange = null; + template.onChange = undefined; template.checkbox.checked = dataElement.value; template.onChange = onChange; @@ -1067,17 +1070,17 @@ export class SettingTreeRenderers { } showContextMenu(element: SettingsTreeSettingElement, settingDOMElement: HTMLElement): void { - const toolbarElement: HTMLElement = settingDOMElement.querySelector('.toolbar-toggle-more'); + const toolbarElement = settingDOMElement.querySelector('.toolbar-toggle-more'); if (toolbarElement) { this._contextMenuService.showContextMenu({ getActions: () => this.settingActions, - getAnchor: () => toolbarElement, + getAnchor: () => toolbarElement, getActionsContext: () => element }); } } - getSettingDOMElementForDOMElement(domElement: HTMLElement): HTMLElement { + getSettingDOMElementForDOMElement(domElement: HTMLElement): HTMLElement | null { const parent = DOM.findParentWithClass(domElement, AbstractSettingRenderer.CONTENTS_CLASS); if (parent) { return parent; @@ -1090,12 +1093,12 @@ export class SettingTreeRenderers { return treeContainer.querySelectorAll(`[${AbstractSettingRenderer.SETTING_KEY_ATTR}="${key}"]`); } - getKeyForDOMElementInSetting(element: HTMLElement): string { + getKeyForDOMElementInSetting(element: HTMLElement): string | null { const settingElement = this.getSettingDOMElementForDOMElement(element); return settingElement && settingElement.getAttribute(AbstractSettingRenderer.SETTING_KEY_ATTR); } - getIdForDOMElementInSetting(element: HTMLElement): string { + getIdForDOMElementInSetting(element: HTMLElement): string | null { const settingElement = this.getSettingDOMElementForDOMElement(element); return settingElement && settingElement.getAttribute(AbstractSettingRenderer.SETTING_ID_ATTR); } @@ -1108,11 +1111,11 @@ function renderValidations(dataElement: SettingsTreeSettingElement, template: IS DOM.addClass(template.containerElement, 'invalid-input'); template.validationErrorMessageElement.innerText = errMsg; const validationError = localize('validationError', "Validation Error."); - template.inputBox.inputElement.parentElement.setAttribute('aria-label', [originalAriaLabel, validationError, errMsg].join(' ')); + template.inputBox.inputElement.parentElement!.setAttribute('aria-label', [originalAriaLabel, validationError, errMsg].join(' ')); if (!calledOnStartup) { ariaAlert(validationError + ' ' + errMsg); } return; } else { - template.inputBox.inputElement.parentElement.setAttribute('aria-label', originalAriaLabel); + template.inputBox.inputElement.parentElement!.setAttribute('aria-label', originalAriaLabel); } } DOM.removeClass(template.containerElement, 'invalid-input'); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 879d9a9e49f..4e7f56b60d8 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -24,7 +24,7 @@ export interface ISettingsEditorViewState { export abstract class SettingsTreeElement { id: string; - parent: SettingsTreeGroupElement; + parent?: SettingsTreeGroupElement; /** * Index assigned in display order, used for paging. @@ -130,7 +130,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } private initLabel(): void { - const displayKeyFormat = settingKeyToDisplayFormat(this.setting.key, this.parent.id); + const displayKeyFormat = settingKeyToDisplayFormat(this.setting.key, this.parent!.id); this._displayLabel = displayKeyFormat.label; this._displayCategory = displayKeyFormat.category; } @@ -161,7 +161,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } if (this.setting.tags) { - this.setting.tags.forEach(tag => this.tags.add(tag)); + this.setting.tags.forEach(tag => this.tags!.add(tag)); } } @@ -207,7 +207,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { if (this.tags) { let hasFilteredTag = true; tagFilters.forEach(tag => { - hasFilteredTag = hasFilteredTag && this.tags.has(tag); + hasFilteredTag = hasFilteredTag && this.tags!.has(tag); }); return hasFilteredTag; } else { @@ -261,12 +261,12 @@ export class SettingsTreeModel { } } - getElementById(id: string): SettingsTreeElement { - return this._treeElementsById.get(id); + getElementById(id: string): SettingsTreeElement | null { + return this._treeElementsById.get(id) || null; } - getElementsByName(name: string): SettingsTreeSettingElement[] { - return this._treeElementsBySettingName.get(name); + getElementsByName(name: string): SettingsTreeSettingElement[] | null { + return this._treeElementsBySettingName.get(name) || null; } updateElementsByName(name: string): void { @@ -274,7 +274,7 @@ export class SettingsTreeModel { return; } - this._treeElementsBySettingName.get(name).forEach(element => { + this._treeElementsBySettingName.get(name)!.forEach(element => { const inspectResult = inspectSetting(element.setting.key, this._viewState.settingsTarget, this._configurationService); element.update(inspectResult); }); @@ -428,7 +428,7 @@ export const enum SearchResultIdx { export class SearchResultModel extends SettingsTreeModel { private rawSearchResults: ISearchResult[]; - private cachedUniqueSearchResults: ISearchResult[]; + private cachedUniqueSearchResults: ISearchResult[] | undefined; private newExtensionSearchResults: ISearchResult; readonly id = 'searchResultModel'; @@ -473,8 +473,8 @@ export class SearchResultModel extends SettingsTreeModel { return this.rawSearchResults; } - setResult(order: SearchResultIdx, result: ISearchResult): void { - this.cachedUniqueSearchResults = null; + setResult(order: SearchResultIdx, result: ISearchResult | null): void { + this.cachedUniqueSearchResults = undefined; this.rawSearchResults = this.rawSearchResults || []; if (!result) { delete this.rawSearchResults[order]; diff --git a/src/vs/workbench/contrib/preferences/browser/tocTree.ts b/src/vs/workbench/contrib/preferences/browser/tocTree.ts index 273471fdcfa..d3fdbdcc6f5 100644 --- a/src/vs/workbench/contrib/preferences/browser/tocTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/tocTree.ts @@ -22,7 +22,7 @@ const $ = DOM.$; export class TOCTreeModel { - private _currentSearchModel: SearchResultModel; + private _currentSearchModel: SearchResultModel | null; private _settingsTreeRoot: SettingsTreeGroupElement; constructor(private _viewState: ISettingsEditorViewState) { @@ -37,7 +37,11 @@ export class TOCTreeModel { this.update(); } - set currentSearchModel(model: SearchResultModel) { + get currentSearchModel(): SearchResultModel | null { + return this._currentSearchModel; + } + + set currentSearchModel(model: SearchResultModel | null) { this._currentSearchModel = model; this.update(); } @@ -61,7 +65,7 @@ export class TOCTreeModel { const childCount = group.children .filter(child => child instanceof SettingsTreeGroupElement) - .reduce((acc, cur) => acc + (cur).count, 0); + .reduce((acc, cur) => acc + (cur).count!, 0); group.count = childCount + this.getGroupCount(group); } diff --git a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts index efdfdce5654..8dccdbea88c 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts @@ -107,14 +107,14 @@ export class SettingsEditor2 extends BaseEditor { private delayedFilterLogging: Delayer; private localSearchDelayer: Delayer; private remoteSearchThrottle: ThrottledDelayer; - private searchInProgress: CancellationTokenSource; + private searchInProgress: CancellationTokenSource | null; private settingFastUpdateDelayer: Delayer; private settingSlowUpdateDelayer: Delayer; - private pendingSettingUpdate: { key: string, value: any }; + private pendingSettingUpdate: { key: string, value: any } | null; private readonly viewState: ISettingsEditorViewState; - private _searchResultModel: SearchResultModel; + private _searchResultModel: SearchResultModel | null; private tocRowFocused: IContextKey; private inSettingsEditorContextKey: IContextKey; @@ -128,7 +128,7 @@ export class SettingsEditor2 extends BaseEditor { private editorMemento: IEditorMemento; - private tocFocusedElement: SettingsTreeGroupElement; + private tocFocusedElement: SettingsTreeGroupElement | null; private settingsTreeScrollTop = 0; constructor( @@ -180,18 +180,19 @@ export class SettingsEditor2 extends BaseEditor { return this.searchResultModel || this.settingsTreeModel; } - private get searchResultModel(): SearchResultModel { + private get searchResultModel(): SearchResultModel | null { return this._searchResultModel; } - private set searchResultModel(value: SearchResultModel) { + private set searchResultModel(value: SearchResultModel | null) { this._searchResultModel = value; DOM.toggleClass(this.rootElement, 'search-mode', !!this._searchResultModel); } - private get currentSettingsContextMenuKeyBindingLabel() { - return this.keybindingService.lookupKeybinding(SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU).getAriaLabel(); + private get currentSettingsContextMenuKeyBindingLabel(): string { + const keybinding = this.keybindingService.lookupKeybinding(SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU); + return (keybinding && keybinding.getAriaLabel()) || ''; } createEditor(parent: HTMLElement): void { @@ -233,7 +234,7 @@ export class SettingsEditor2 extends BaseEditor { } private restoreCachedState(): void { - const cachedState = this.editorMemento.loadEditorState(this.group, this.input); + const cachedState = this.group && this.input && this.editorMemento.loadEditorState(this.group, this.input); if (cachedState && typeof cachedState.target === 'object') { cachedState.target = URI.revive(cachedState.target); } @@ -268,7 +269,10 @@ export class SettingsEditor2 extends BaseEditor { clearInput(): void { this.inSettingsEditorContextKey.set(false); - this.editorMemento.clearEditorState(this.input, this.group); + if (this.input) { + this.editorMemento.clearEditorState(this.input, this.group); + } + super.clearInput(); } @@ -315,7 +319,12 @@ export class SettingsEditor2 extends BaseEditor { } showContextMenu(): void { - const settingDOMElement = this.settingRenderers.getSettingDOMElementForDOMElement(this.getActiveElementInSettingsTree()); + const activeElement = this.getActiveElementInSettingsTree(); + if (!activeElement) { + return; + } + + const settingDOMElement = this.settingRenderers.getSettingDOMElementForDOMElement(activeElement); if (!settingDOMElement) { return; } @@ -383,9 +392,10 @@ export class SettingsEditor2 extends BaseEditor { 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; this.countElement.style.backgroundColor = background; - this.countElement.style.color = colors.badgeForeground.toString(); + this.countElement.style.color = foreground; this.countElement.style.borderWidth = border ? '1px' : null; this.countElement.style.borderStyle = border ? 'solid' : null; @@ -412,6 +422,10 @@ export class SettingsEditor2 extends BaseEditor { const elements = this.currentSettingsModel.getElementsByName(evt.targetKey); if (elements && elements[0]) { let sourceTop = this.settingsTree.getRelativeTop(evt.source); + if (typeof sourceTop !== 'number') { + return; + } + if (sourceTop < 0) { // e.g. clicked a searched element, now the search has been cleared sourceTop = 0.5; @@ -435,12 +449,12 @@ export class SettingsEditor2 extends BaseEditor { } } - switchToSettingsFile(): Promise { + switchToSettingsFile(): Promise { const query = parseQuery(this.searchWidget.getValue()); return this.openSettingsFile(query.query); } - private openSettingsFile(query?: string): Promise { + private openSettingsFile(query?: string): Promise { const currentSettingsTarget = this.settingsTargetsWidget.settingsTarget; const options: ISettingsEditorOptions = { query }; @@ -550,7 +564,7 @@ export class SettingsEditor2 extends BaseEditor { this.viewState)); this._register(this.tocTree.onDidChangeFocus(e => { - const element: SettingsTreeGroupElement = e.elements[0]; + const element: SettingsTreeGroupElement | null = e.elements[0]; if (this.tocFocusedElement === element) { return; } @@ -559,7 +573,7 @@ export class SettingsEditor2 extends BaseEditor { this.tocTree.setSelection(element ? [element] : []); if (this.searchResultModel) { if (this.viewState.filterToCategory !== element) { - this.viewState.filterToCategory = element; + this.viewState.filterToCategory = element || undefined; this.renderTree(); this.settingsTree.scrollTop = 0; } @@ -672,6 +686,10 @@ export class SettingsEditor2 extends BaseEditor { this.tocTree.reveal(element); const elementTop = this.tocTree.getRelativeTop(element); + if (typeof elementTop !== 'number') { + return; + } + this.tocTree.collapseAll(); ancestors.forEach(e => this.tocTree.expand(e)); @@ -738,17 +756,17 @@ export class SettingsEditor2 extends BaseEditor { }); } - private reportModifiedSetting(props: { key: string, query: string, searchResults: ISearchResult[], rawResults: ISearchResult[], showConfiguredOnly: boolean, isReset: boolean, settingsTarget: SettingsTarget }): void { + private reportModifiedSetting(props: { key: string, query: string, searchResults: ISearchResult[] | null, rawResults: ISearchResult[] | null, showConfiguredOnly: boolean, isReset: boolean, settingsTarget: SettingsTarget }): void { this.pendingSettingUpdate = null; - const remoteResult = props.searchResults && props.searchResults[SearchResultIdx.Remote]; - const localResult = props.searchResults && props.searchResults[SearchResultIdx.Local]; - - let groupId = undefined; - let nlpIndex = undefined; - let displayIndex = undefined; + let groupId: string | undefined = undefined; + let nlpIndex: number | undefined = undefined; + let displayIndex: number | undefined = undefined; if (props.searchResults) { - const localIndex = arrays.firstIndex(localResult.filterMatches, m => m.setting.key === props.key); + const remoteResult = props.searchResults[SearchResultIdx.Remote]; + const localResult = props.searchResults[SearchResultIdx.Local]; + + const localIndex = arrays.firstIndex(localResult!.filterMatches, m => m.setting.key === props.key); groupId = localIndex >= 0 ? 'local' : 'remote'; @@ -860,9 +878,9 @@ export class SettingsEditor2 extends BaseEditor { } const commonlyUsed = resolveSettingsTree(commonlyUsedData, dividedGroups.core); - resolvedSettingsRoot.children.unshift(commonlyUsed.tree); + resolvedSettingsRoot.children!.unshift(commonlyUsed.tree); - resolvedSettingsRoot.children.push(resolveExtensionsSettings(dividedGroups.extension || [])); + resolvedSettingsRoot.children!.push(resolveExtensionsSettings(dividedGroups.extension || [])); if (this.searchResultModel) { this.searchResultModel.updateChildren(); @@ -872,7 +890,7 @@ export class SettingsEditor2 extends BaseEditor { this.settingsTreeModel.update(resolvedSettingsRoot); // Make sure that all extensions' settings are included in search results - const cachedState = this.editorMemento.loadEditorState(this.group, this.input); + const cachedState = this.group && this.input && this.editorMemento.loadEditorState(this.group, this.input); if (cachedState && cachedState.searchQuery) { this.triggerSearch(cachedState.searchQuery); } else { @@ -895,7 +913,7 @@ export class SettingsEditor2 extends BaseEditor { private updateElementsByKey(keys: string[]): Promise { if (keys.length) { if (this.searchResultModel) { - keys.forEach(key => this.searchResultModel.updateElementsByName(key)); + keys.forEach(key => this.searchResultModel!.updateElementsByName(key)); } if (this.settingsTreeModel) { @@ -923,7 +941,8 @@ export class SettingsEditor2 extends BaseEditor { } // If a setting control is currently focused, schedule a refresh for later - const focusedSetting = this.settingRenderers.getSettingDOMElementForDOMElement(this.getActiveElementInSettingsTree()); + const activeElement = this.getActiveElementInSettingsTree(); + const focusedSetting = activeElement && this.settingRenderers.getSettingDOMElementForDOMElement(activeElement); if (focusedSetting && !force) { // If a single setting is being refreshed, it's ok to refresh now if that is not the focused setting if (key) { @@ -978,7 +997,7 @@ export class SettingsEditor2 extends BaseEditor { const isModified = dataElements && dataElements[0] && dataElements[0].isConfigured; // all elements are either configured or not const elements = this.settingRenderers.getDOMElementsForSettingKey(this.settingsTree.getHTMLElement(), key); if (elements && elements[0]) { - DOM.toggleClass(elements[0], 'is-configured', isModified); + DOM.toggleClass(elements[0], 'is-configured', !!isModified); } } @@ -987,12 +1006,12 @@ export class SettingsEditor2 extends BaseEditor { this.delayedFilterLogging.cancel(); this.triggerSearch(query.replace(/›/g, ' ')).then(() => { if (query && this.searchResultModel) { - this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(query, this.searchResultModel.getUniqueResults())); + this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(query, this.searchResultModel!.getUniqueResults())); } }); } - private parseSettingFromJSON(query: string): string { + private parseSettingFromJSON(query: string): string | null { const match = query.match(/"([a-zA-Z.]+)": /); return match && match[1]; } @@ -1002,7 +1021,7 @@ export class SettingsEditor2 extends BaseEditor { if (query) { const parsedQuery = parseQuery(query); query = parsedQuery.query; - parsedQuery.tags.forEach(tag => this.viewState.tagFilters.add(tag)); + parsedQuery.tags.forEach(tag => this.viewState.tagFilters!.add(tag)); } if (query && query !== '@') { @@ -1023,7 +1042,7 @@ export class SettingsEditor2 extends BaseEditor { this.searchInProgress = null; } - this.viewState.filterToCategory = null; + this.viewState.filterToCategory = undefined; this.tocTreeModel.currentSearchModel = this.searchResultModel; this.onSearchModeToggled(); @@ -1043,7 +1062,7 @@ export class SettingsEditor2 extends BaseEditor { this.refreshTOCTree(); } - return Promise.resolve(null); + return Promise.resolve(); } /** @@ -1121,18 +1140,18 @@ export class SettingsEditor2 extends BaseEditor { if (result && !result.exactMatch) { this.remoteSearchThrottle.trigger(() => { return searchInProgress && !searchInProgress.token.isCancellationRequested ? - this.remoteSearchPreferences(query, this.searchInProgress.token) : - Promise.resolve(null); + this.remoteSearchPreferences(query, this.searchInProgress!.token) : + Promise.resolve(); }); } }); } else { - return Promise.resolve(null); + return Promise.resolve(); } }); } - private localFilterPreferences(query: string, token?: CancellationToken): Promise { + private localFilterPreferences(query: string, token?: CancellationToken): Promise { const localSearchProvider = this.preferencesSearchService.getLocalSearchProvider(query); return this.filterOrSearchPreferences(query, SearchResultIdx.Local, localSearchProvider, token); } @@ -1147,7 +1166,7 @@ export class SettingsEditor2 extends BaseEditor { ]).then(() => { }); } - private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider: ISearchProvider, token?: CancellationToken): Promise { + private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider?: ISearchProvider, token?: CancellationToken): Promise { return this._filterOrSearchPreferencesModel(query, this.defaultSettingsEditorModel, searchProvider, token).then(result => { if (token && token.isCancellationRequested) { // Handle cancellation like this because cancellation is lost inside the search provider due to async/await @@ -1165,7 +1184,7 @@ export class SettingsEditor2 extends BaseEditor { } this.tocTree.setSelection([]); - this.viewState.filterToCategory = null; + this.viewState.filterToCategory = undefined; this.tocTree.expandAll(); return this.renderTree(undefined, true).then(() => result); @@ -1193,7 +1212,7 @@ export class SettingsEditor2 extends BaseEditor { } } - private _filterOrSearchPreferencesModel(filter: string, model: ISettingsEditorModel, provider: ISearchProvider, token?: CancellationToken): Promise { + private _filterOrSearchPreferencesModel(filter: string, model: ISettingsEditorModel, provider?: ISearchProvider, token?: CancellationToken): Promise { const searchP = provider ? provider.searchModel(model, token) : Promise.resolve(null); return searchP .then(null, err => { @@ -1212,7 +1231,7 @@ export class SettingsEditor2 extends BaseEditor { this.telemetryService.publicLog('settingsEditor.searchError', { message, filter }); this.logService.info('Setting search error: ' + message); } - return null; + return Promise.resolve(null); } }); } @@ -1232,7 +1251,9 @@ export class SettingsEditor2 extends BaseEditor { if (this.isVisible()) { const searchQuery = this.searchWidget.getValue().trim(); const target = this.settingsTargetsWidget.settingsTarget as SettingsTarget; - this.editorMemento.saveEditorState(this.group, this.input, { searchQuery, target }); + if (this.group && this.input) { + this.editorMemento.saveEditorState(this.group, this.input, { searchQuery, target }); + } } super.saveState(); From 6da595150d8e32ea1a57d8d78d0252bfebedbb68 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 6 Mar 2019 19:29:45 +0100 Subject: [PATCH 166/172] Fix simple file picker in empty workspace --- .../services/dialogs/electron-browser/remoteFileDialog.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts index 1861f1c0bdf..299ac57f673 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/remoteFileDialog.ts @@ -97,8 +97,8 @@ export class RemoteFileDialog { } private getOptions(options: ISaveDialogOptions | IOpenDialogOptions): IOpenDialogOptions | undefined { - const defaultUri = options.defaultUri ? options.defaultUri : URI.from({ scheme: REMOTE_HOST_SCHEME, authority: this.remoteAuthority, path: '/' }); - if (!this.remoteFileService.canHandleResource(defaultUri)) { + const defaultUri = options.defaultUri ? options.defaultUri : URI.from({ scheme: this.scheme, authority: this.remoteAuthority, path: '/' }); + if ((this.scheme !== Schemas.file) && !this.remoteFileService.canHandleResource(defaultUri)) { this.notificationService.info(nls.localize('remoteFileDialog.notConnectedToRemote', 'File system provider for {0} is not available.', defaultUri.toString())); return undefined; } @@ -119,7 +119,7 @@ export class RemoteFileDialog { private async pickResource(options: IOpenDialogOptions, isSave: boolean = false): Promise { this.allowFolderSelection = !!options.canSelectFolders; this.allowFileSelection = !!options.canSelectFiles; - let homedir: URI = options.defaultUri && options.defaultUri.scheme === REMOTE_HOST_SCHEME ? options.defaultUri : this.workspaceContextService.getWorkspace().folders[0].uri; + let homedir: URI = options.defaultUri ? options.defaultUri : this.workspaceContextService.getWorkspace().folders[0].uri; let trailing: string | undefined; let stat: IFileStat | undefined; let ext: string = resources.extname(options.defaultUri); From c93f5e35601345b0696ba07174a388658cf9e13c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2019 17:19:01 -0800 Subject: [PATCH 167/172] Use regular expression to identify config file names instead of singe file name --- .../typescript-language-features/src/languageProvider.ts | 2 +- .../src/utils/languageDescription.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 6f122fcb633..84dbb8e946d 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -90,7 +90,7 @@ export default class LanguageProvider extends Disposable { } const base = basename(resource.fsPath); - return !!base && base === this.description.configFile; + return !!base && (!!this.description.configFilePattern && this.description.configFilePattern.test(base)); } private get id(): string { diff --git a/extensions/typescript-language-features/src/utils/languageDescription.ts b/extensions/typescript-language-features/src/utils/languageDescription.ts index 32cec300ebd..377c7c3b8e8 100644 --- a/extensions/typescript-language-features/src/utils/languageDescription.ts +++ b/extensions/typescript-language-features/src/utils/languageDescription.ts @@ -17,7 +17,7 @@ export interface LanguageDescription { readonly diagnosticSource: string; readonly diagnosticLanguage: DiagnosticLanguage; readonly modeIds: string[]; - readonly configFile?: string; + readonly configFilePattern?: RegExp; readonly isExternal?: boolean; } @@ -28,13 +28,13 @@ export const standardLanguageDescriptions: LanguageDescription[] = [ diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.TypeScript, modeIds: [languageModeIds.typescript, languageModeIds.typescriptreact], - configFile: 'tsconfig.json' + configFilePattern: /tsconfig(\..*)?\.json/gi }, { id: 'javascript', diagnosticOwner: 'typescript', diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.JavaScript, modeIds: [languageModeIds.javascript, languageModeIds.javascriptreact], - configFile: 'jsconfig.json' + configFilePattern: /jsconfig(\..*)?\.json/gi } ]; From 4bfec9c80f2d6b7f4546df0d68b756e555a606c9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 6 Mar 2019 10:49:49 -0800 Subject: [PATCH 168/172] Make sure we match whole file name for config file --- .../src/utils/languageDescription.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/typescript-language-features/src/utils/languageDescription.ts b/extensions/typescript-language-features/src/utils/languageDescription.ts index 377c7c3b8e8..b9f279dc509 100644 --- a/extensions/typescript-language-features/src/utils/languageDescription.ts +++ b/extensions/typescript-language-features/src/utils/languageDescription.ts @@ -28,13 +28,13 @@ export const standardLanguageDescriptions: LanguageDescription[] = [ diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.TypeScript, modeIds: [languageModeIds.typescript, languageModeIds.typescriptreact], - configFilePattern: /tsconfig(\..*)?\.json/gi + configFilePattern: /^tsconfig(\..*)?\.json$/gi }, { id: 'javascript', diagnosticOwner: 'typescript', diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.JavaScript, modeIds: [languageModeIds.javascript, languageModeIds.javascriptreact], - configFilePattern: /jsconfig(\..*)?\.json/gi + configFilePattern: /^jsconfig(\..*)?\.json$/gi } ]; From a4b49166d0768624bf76cfd86ee1a166de844768 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 6 Mar 2019 22:16:44 +0100 Subject: [PATCH 169/172] Fix #69110 --- src/tsconfig.strictNullChecks.json | 6 +- .../api/node/extHostOutputService.ts | 2 +- .../output.contribution.ts | 2 +- .../contrib/output/browser/outputServices.ts | 291 +++++++ .../output/electron-browser/outputServices.ts | 813 ------------------ .../output/common/outputChannelModel.ts | 413 +++++++++ .../common/outputChannelModelService.ts | 14 + .../output/node/outputAppender.ts | 0 .../output/node/outputChannelModelService.ts | 192 +++++ src/vs/workbench/workbench.main.ts | 3 +- 10 files changed, 917 insertions(+), 819 deletions(-) rename src/vs/workbench/contrib/output/{electron-browser => browser}/output.contribution.ts (99%) create mode 100644 src/vs/workbench/contrib/output/browser/outputServices.ts delete mode 100644 src/vs/workbench/contrib/output/electron-browser/outputServices.ts create mode 100644 src/vs/workbench/services/output/common/outputChannelModel.ts create mode 100644 src/vs/workbench/services/output/common/outputChannelModelService.ts rename src/vs/workbench/{contrib => services}/output/node/outputAppender.ts (100%) create mode 100644 src/vs/workbench/services/output/node/outputChannelModelService.ts diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 6ac1d410616..a674809e8b0 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -27,6 +27,7 @@ "./vs/workbench/services/files/node/watcher/**/*", "./vs/workbench/services/themes/**/*.ts", "./vs/workbench/services/bulkEdit/**/*.ts", + "./vs/workbench/services/output/**/*.ts", "./vs/workbench/services/progress/**/*.ts", "./vs/workbench/services/preferences/**/*.ts", "./vs/workbench/services/timer/**/*.ts", @@ -313,9 +314,8 @@ "./vs/workbench/contrib/output/common/output.ts", "./vs/workbench/contrib/output/common/outputLinkComputer.ts", "./vs/workbench/contrib/output/common/outputLinkProvider.ts", - "./vs/workbench/contrib/output/electron-browser/output.contribution.ts", - "./vs/workbench/contrib/output/electron-browser/outputServices.ts", - "./vs/workbench/contrib/output/node/outputAppender.ts", + "./vs/workbench/contrib/output/browser/output.contribution.ts", + "./vs/workbench/contrib/output/browser/outputServices.ts", "./vs/workbench/contrib/preferences/browser/preferencesActions.ts", "./vs/workbench/contrib/preferences/browser/preferencesWidgets.ts", "./vs/workbench/contrib/preferences/browser/settingsLayout.ts", diff --git a/src/vs/workbench/api/node/extHostOutputService.ts b/src/vs/workbench/api/node/extHostOutputService.ts index e009ffb6dcb..25ebdd8137d 100644 --- a/src/vs/workbench/api/node/extHostOutputService.ts +++ b/src/vs/workbench/api/node/extHostOutputService.ts @@ -7,7 +7,7 @@ import { MainContext, MainThreadOutputServiceShape, IMainContext, ExtHostOutputS import * as vscode from 'vscode'; import { URI } from 'vs/base/common/uri'; import { join } from 'vs/base/common/path'; -import { OutputAppender } from 'vs/workbench/contrib/output/node/outputAppender'; +import { OutputAppender } from 'vs/workbench/services/output/node/outputAppender'; import { toLocalISOString } from 'vs/base/common/date'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/contrib/output/electron-browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts similarity index 99% rename from src/vs/workbench/contrib/output/electron-browser/output.contribution.ts rename to src/vs/workbench/contrib/output/browser/output.contribution.ts index 65e36ae6aab..273ac9f397d 100644 --- a/src/vs/workbench/contrib/output/electron-browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -10,7 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { MenuId, MenuRegistry, SyncActionDescriptor, registerAction } from 'vs/platform/actions/common/actions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { OutputService, LogContentProvider } from 'vs/workbench/contrib/output/electron-browser/outputServices'; +import { OutputService, LogContentProvider } from 'vs/workbench/contrib/output/browser/outputServices'; import { ToggleOutputAction, ClearOutputAction, OpenLogOutputFile, ShowLogsOutputChannelAction, OpenOutputLogFileAction } from 'vs/workbench/contrib/output/browser/outputActions'; import { OUTPUT_MODE_ID, OUTPUT_MIME, OUTPUT_PANEL_ID, IOutputService, CONTEXT_IN_OUTPUT, LOG_SCHEME, LOG_MODE_ID, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT } from 'vs/workbench/contrib/output/common/output'; import { PanelRegistry, Extensions, PanelDescriptor } from 'vs/workbench/browser/panel'; diff --git a/src/vs/workbench/contrib/output/browser/outputServices.ts b/src/vs/workbench/contrib/output/browser/outputServices.ts new file mode 100644 index 00000000000..9f545ac8384 --- /dev/null +++ b/src/vs/workbench/contrib/output/browser/outputServices.ts @@ -0,0 +1,291 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { Event, Emitter } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { EditorOptions } from 'vs/workbench/common/editor'; +import { IOutputChannelDescriptor, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, LOG_SCHEME, CONTEXT_ACTIVE_LOG_OUTPUT, LOG_MIME, OUTPUT_MIME } from 'vs/workbench/contrib/output/common/output'; +import { OutputPanel } from 'vs/workbench/contrib/output/browser/outputPanel'; +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { OutputLinkProvider } from 'vs/workbench/contrib/output/common/outputLinkProvider'; +import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; +import { ITextModel } from 'vs/editor/common/model'; +import { IPanel } from 'vs/workbench/common/panel'; +import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { ILogService } from 'vs/platform/log/common/log'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { IOutputChannelModel, IOutputChannelModelService } from 'vs/workbench/services/output/common/outputChannelModel'; + +const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel'; + +class OutputChannel extends Disposable implements IOutputChannel { + + scrollLock: boolean = false; + readonly model: IOutputChannelModel; + readonly id: string; + readonly label: string; + + constructor( + readonly outputChannelDescriptor: IOutputChannelDescriptor, + @IOutputChannelModelService outputChannelModelService: IOutputChannelModelService + ) { + super(); + this.id = outputChannelDescriptor.id; + this.label = outputChannelDescriptor.label; + this.model = this._register(outputChannelModelService.createOutputChannelModel(this.id, URI.from({ scheme: OUTPUT_SCHEME, path: this.id }), outputChannelDescriptor.log ? LOG_MIME : OUTPUT_MIME, outputChannelDescriptor.file)); + } + + append(output: string): void { + this.model.append(output); + } + + update(): void { + this.model.update(); + } + + clear(till?: number): void { + this.model.clear(till); + } +} + +export class OutputService extends Disposable implements IOutputService, ITextModelContentProvider { + + public _serviceBrand: any; + + private channels: Map = new Map(); + private activeChannelIdInStorage: string; + private activeChannel: OutputChannel | null; + + private readonly _onActiveOutputChannel = new Emitter(); + readonly onActiveOutputChannel: Event = this._onActiveOutputChannel.event; + + private _outputPanel: OutputPanel; + + constructor( + @IStorageService private readonly storageService: IStorageService, + @IInstantiationService private readonly instantiationService: IInstantiationService, + @IPanelService private readonly panelService: IPanelService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @ITextModelService textModelResolverService: ITextModelService, + @IEnvironmentService environmentService: IEnvironmentService, + @IWindowService windowService: IWindowService, + @ILogService private readonly logService: ILogService, + @ILifecycleService private readonly lifecycleService: ILifecycleService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + ) { + super(); + this.activeChannelIdInStorage = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, ''); + + // Register as text model content provider for output + textModelResolverService.registerTextModelContentProvider(OUTPUT_SCHEME, this); + instantiationService.createInstance(OutputLinkProvider); + + // Create output channels for already registered channels + const registry = Registry.as(Extensions.OutputChannels); + for (const channelIdentifier of registry.getChannels()) { + this.onDidRegisterChannel(channelIdentifier.id); + } + this._register(registry.onDidRegisterChannel(this.onDidRegisterChannel, this)); + + this._register(panelService.onDidPanelOpen(({ panel, focus }) => this.onDidPanelOpen(panel, !focus), this)); + this._register(panelService.onDidPanelClose(this.onDidPanelClose, this)); + + // Set active channel to first channel if not set + if (!this.activeChannel) { + const channels = this.getChannelDescriptors(); + this.activeChannel = channels && channels.length > 0 ? this.getChannel(channels[0].id) : null; + } + + this._register(this.lifecycleService.onShutdown(() => this.dispose())); + this._register(this.storageService.onWillSaveState(() => this.saveState())); + } + + provideTextContent(resource: URI): Promise | null { + const channel = this.getChannel(resource.path); + if (channel) { + return channel.model.loadModel(); + } + return null; + } + + showChannel(id: string, preserveFocus?: boolean): Promise { + const channel = this.getChannel(id); + if (!channel || this.isChannelShown(channel)) { + if (this._outputPanel && !preserveFocus) { + this._outputPanel.focus(); + } + return Promise.resolve(undefined); + } + + this.activeChannel = channel; + let promise: Promise; + if (this.isPanelShown()) { + promise = this.doShowChannel(channel, !!preserveFocus); + } else { + this.panelService.openPanel(OUTPUT_PANEL_ID); + promise = this.doShowChannel(this.activeChannel, !!preserveFocus); + } + return promise.then(() => this._onActiveOutputChannel.fire(id)); + } + + getChannel(id: string): OutputChannel | null { + return this.channels.get(id) || null; + } + + getChannelDescriptors(): IOutputChannelDescriptor[] { + return Registry.as(Extensions.OutputChannels).getChannels(); + } + + getActiveChannel(): IOutputChannel | null { + return this.activeChannel; + } + + private onDidRegisterChannel(channelId: string): void { + const channel = this.createChannel(channelId); + this.channels.set(channelId, channel); + if (this.activeChannelIdInStorage === channelId) { + this.activeChannel = channel; + this.onDidPanelOpen(this.panelService.getActivePanel(), true) + .then(() => this._onActiveOutputChannel.fire(channelId)); + } + } + + private onDidPanelOpen(panel: IPanel | null, preserveFocus: boolean): Promise { + if (panel && panel.getId() === OUTPUT_PANEL_ID) { + this._outputPanel = this.panelService.getActivePanel(); + if (this.activeChannel) { + return this.doShowChannel(this.activeChannel, preserveFocus); + } + } + return Promise.resolve(undefined); + } + + private onDidPanelClose(panel: IPanel): void { + if (this._outputPanel && panel.getId() === OUTPUT_PANEL_ID) { + CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(false); + this._outputPanel.clearInput(); + } + } + + private createChannel(id: string): OutputChannel { + const channelDisposables: IDisposable[] = []; + const channel = this.instantiateChannel(id); + channel.model.onDidAppendedContent(() => { + if (!channel.scrollLock) { + const panel = this.panelService.getActivePanel(); + if (panel && panel.getId() === OUTPUT_PANEL_ID && this.isChannelShown(channel)) { + let outputPanel = panel; + outputPanel.revealLastLine(); + } + } + }, channelDisposables); + channel.model.onDispose(() => { + if (this.activeChannel === channel) { + const channels = this.getChannelDescriptors(); + const channel = channels.length ? this.getChannel(channels[0].id) : null; + if (channel && this.isPanelShown()) { + this.showChannel(channel.id, true); + } else { + this.activeChannel = channel; + if (this.activeChannel) { + this._onActiveOutputChannel.fire(this.activeChannel.id); + } + } + } + Registry.as(Extensions.OutputChannels).removeChannel(id); + dispose(channelDisposables); + }, channelDisposables); + + return channel; + } + + private instantiateChannel(id: string): OutputChannel { + const channelData = Registry.as(Extensions.OutputChannels).getChannel(id); + if (!channelData) { + this.logService.error(`Channel '${id}' is not registered yet`); + throw new Error(`Channel '${id}' is not registered yet`); + } + return this.instantiationService.createInstance(OutputChannel, channelData); + } + + private doShowChannel(channel: OutputChannel, preserveFocus: boolean): Promise { + if (this._outputPanel) { + CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(!!channel.outputChannelDescriptor.file && channel.outputChannelDescriptor.log); + return this._outputPanel.setInput(this.createInput(channel), EditorOptions.create({ preserveFocus }), CancellationToken.None) + .then(() => { + if (!preserveFocus) { + this._outputPanel.focus(); + } + }); + } + return Promise.resolve(undefined); + } + + private isChannelShown(channel: IOutputChannel): boolean { + return this.isPanelShown() && this.activeChannel === channel; + } + + private isPanelShown(): boolean { + const panel = this.panelService.getActivePanel(); + return !!panel && panel.getId() === OUTPUT_PANEL_ID; + } + + private createInput(channel: IOutputChannel): ResourceEditorInput { + const resource = URI.from({ scheme: OUTPUT_SCHEME, path: channel.id }); + return this.instantiationService.createInstance(ResourceEditorInput, nls.localize('output', "{0} - Output", channel.label), nls.localize('channel', "Output channel for '{0}'", channel.label), resource); + } + + private saveState(): void { + if (this.activeChannel) { + this.storageService.store(OUTPUT_ACTIVE_CHANNEL_KEY, this.activeChannel.id, StorageScope.WORKSPACE); + } + } +} + +export class LogContentProvider { + + private channelModels: Map = new Map(); + + constructor( + @IOutputService private readonly outputService: IOutputService, + @IOutputChannelModelService private readonly outputChannelModelService: IOutputChannelModelService + ) { + } + + provideTextContent(resource: URI): Promise | null { + if (resource.scheme === LOG_SCHEME) { + let channelModel = this.getChannelModel(resource); + if (channelModel) { + return channelModel.loadModel(); + } + } + return null; + } + + private getChannelModel(resource: URI): IOutputChannelModel | undefined { + const channelId = resource.path; + let channelModel = this.channelModels.get(channelId); + if (!channelModel) { + const channelDisposables: IDisposable[] = []; + const outputChannelDescriptor = this.outputService.getChannelDescriptors().filter(({ id }) => id === channelId)[0]; + if (outputChannelDescriptor && outputChannelDescriptor.file) { + channelModel = this.outputChannelModelService.createOutputChannelModel(channelId, resource, outputChannelDescriptor.log ? LOG_MIME : OUTPUT_MIME, outputChannelDescriptor.file); + channelModel.onDispose(() => dispose(channelDisposables), channelDisposables); + this.channelModels.set(channelId, channelModel); + } + } + return channelModel; + } +} \ No newline at end of file diff --git a/src/vs/workbench/contrib/output/electron-browser/outputServices.ts b/src/vs/workbench/contrib/output/electron-browser/outputServices.ts deleted file mode 100644 index 60db5a4544d..00000000000 --- a/src/vs/workbench/contrib/output/electron-browser/outputServices.ts +++ /dev/null @@ -1,813 +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 { join, dirname } from 'vs/base/common/path'; -import * as strings from 'vs/base/common/strings'; -import * as extfs from 'vs/base/node/extfs'; -import { Event, Emitter } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; -import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorOptions } from 'vs/workbench/common/editor'; -import { IOutputChannelDescriptor, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, OUTPUT_MIME, LOG_SCHEME, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT, MAX_OUTPUT_LENGTH, IFileOutputChannelDescriptor } from 'vs/workbench/contrib/output/common/output'; -import { OutputPanel } from 'vs/workbench/contrib/output/browser/outputPanel'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { IModelService } from 'vs/editor/common/services/modelService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { OutputLinkProvider } from 'vs/workbench/contrib/output/common/outputLinkProvider'; -import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; -import { ITextModel } from 'vs/editor/common/model'; -import { IModeService } from 'vs/editor/common/services/modeService'; -import { RunOnceScheduler, ThrottledDelayer } from 'vs/base/common/async'; -import { EditOperation } from 'vs/editor/common/core/editOperation'; -import { Position } from 'vs/editor/common/core/position'; -import { IFileService } from 'vs/platform/files/common/files'; -import { IPanel } from 'vs/workbench/common/panel'; -import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { toLocalISOString } from 'vs/base/common/date'; -import { IWindowService } from 'vs/platform/windows/common/windows'; -import { ILogService } from 'vs/platform/log/common/log'; -import { binarySearch } from 'vs/base/common/arrays'; -import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { OutputAppender } from 'vs/workbench/contrib/output/node/outputAppender'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { isNumber } from 'vs/base/common/types'; - -const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel'; - -let watchingOutputDir = false; -let callbacks: ((eventType: string, fileName?: string) => void)[] = []; -function watchOutputDirectory(outputDir: string, logService: ILogService, onChange: (eventType: string, fileName: string) => void): IDisposable { - callbacks.push(onChange); - if (!watchingOutputDir) { - const watcherDisposable = extfs.watch(outputDir, (eventType, fileName) => { - for (const callback of callbacks) { - callback(eventType, fileName); - } - }, (error: string) => { - logService.error(error); - }); - watchingOutputDir = true; - return toDisposable(() => { - callbacks = []; - watcherDisposable.dispose(); - }); - } - return toDisposable(() => { }); -} - -interface OutputChannel extends IOutputChannel { - readonly file: URI | null; - readonly onDidAppendedContent: Event; - readonly onDispose: Event; - loadModel(): Promise; -} - -abstract class AbstractFileOutputChannel extends Disposable implements OutputChannel { - - scrollLock: boolean = false; - - protected _onDidAppendedContent = new Emitter(); - readonly onDidAppendedContent: Event = this._onDidAppendedContent.event; - - protected _onDispose = new Emitter(); - readonly onDispose: Event = this._onDispose.event; - - private readonly mimeType: string; - protected modelUpdater: RunOnceScheduler; - protected model: ITextModel | null; - readonly file: URI; - - protected startOffset: number = 0; - protected endOffset: number = 0; - - constructor( - readonly outputChannelDescriptor: IFileOutputChannelDescriptor, - private readonly modelUri: URI, - protected fileService: IFileService, - protected modelService: IModelService, - protected modeService: IModeService, - ) { - super(); - this.mimeType = outputChannelDescriptor.log ? LOG_MIME : OUTPUT_MIME; - this.file = this.outputChannelDescriptor.file; - this.modelUpdater = new RunOnceScheduler(() => this.updateModel(), 300); - this._register(toDisposable(() => this.modelUpdater.cancel())); - } - - get id(): string { - return this.outputChannelDescriptor.id; - } - - get label(): string { - return this.outputChannelDescriptor.label; - } - - clear(till?: number): void { - if (this.modelUpdater.isScheduled()) { - this.modelUpdater.cancel(); - this.onUpdateModelCancelled(); - } - if (this.model) { - this.model.setValue(''); - } - this.endOffset = isNumber(till) ? till : this.endOffset; - this.startOffset = this.endOffset; - } - - update(): void { } - - protected createModel(content: string): ITextModel { - if (this.model) { - this.model.setValue(content); - } else { - this.model = this.modelService.createModel(content, this.modeService.create(this.mimeType), this.modelUri); - this.onModelCreated(this.model); - const disposables: IDisposable[] = []; - disposables.push(this.model.onWillDispose(() => { - this.onModelWillDispose(this.model); - this.model = null; - dispose(disposables); - })); - } - return this.model; - } - - appendToModel(content: string): void { - if (this.model && content) { - const lastLine = this.model.getLineCount(); - const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine); - this.model.applyEdits([EditOperation.insert(new Position(lastLine, lastLineMaxColumn), content)]); - this._onDidAppendedContent.fire(); - } - } - - abstract loadModel(): Promise; - abstract append(message: string); - - protected onModelCreated(model: ITextModel) { } - protected onModelWillDispose(model: ITextModel | null) { } - protected onUpdateModelCancelled() { } - protected updateModel() { } - - dispose(): void { - this._onDispose.fire(); - super.dispose(); - } -} - -/** - * An output channel that stores appended messages in a backup file. - */ -class OutputChannelBackedByFile extends AbstractFileOutputChannel implements OutputChannel { - - private appender: OutputAppender; - private appendedMessage = ''; - private loadingFromFileInProgress: boolean = false; - private resettingDelayer: ThrottledDelayer; - private readonly rotatingFilePath: string; - - constructor( - outputChannelDescriptor: IFileOutputChannelDescriptor, - modelUri: URI, - @IFileService fileService: IFileService, - @IModelService modelService: IModelService, - @IModeService modeService: IModeService, - @ILogService logService: ILogService - ) { - super(outputChannelDescriptor, modelUri, fileService, modelService, modeService); - - // Use one rotating file to check for main file reset - this.appender = new OutputAppender(this.id, this.file.fsPath); - this.rotatingFilePath = `${outputChannelDescriptor.id}.1.log`; - this._register(watchOutputDirectory(dirname(this.file.fsPath), logService, (eventType, file) => this.onFileChangedInOutputDirector(eventType, file))); - - this.resettingDelayer = new ThrottledDelayer(50); - } - - append(message: string): void { - // update end offset always as message is read - this.endOffset = this.endOffset + Buffer.from(message).byteLength; - if (this.loadingFromFileInProgress) { - this.appendedMessage += message; - } else { - this.write(message); - if (this.model) { - this.appendedMessage += message; - if (!this.modelUpdater.isScheduled()) { - this.modelUpdater.schedule(); - } - } - } - } - - clear(till?: number): void { - super.clear(till); - this.appendedMessage = ''; - } - - loadModel(): Promise { - this.loadingFromFileInProgress = true; - if (this.modelUpdater.isScheduled()) { - this.modelUpdater.cancel(); - } - this.appendedMessage = ''; - return this.loadFile() - .then(content => { - if (this.endOffset !== this.startOffset + Buffer.from(content).byteLength) { - // Queue content is not written into the file - // Flush it and load file again - this.flush(); - return this.loadFile(); - } - return content; - }) - .then(content => { - if (this.appendedMessage) { - this.write(this.appendedMessage); - this.appendedMessage = ''; - } - this.loadingFromFileInProgress = false; - return this.createModel(content); - }); - } - - private resetModel(): Promise { - this.startOffset = 0; - this.endOffset = 0; - if (this.model) { - return this.loadModel().then(() => undefined); - } - return Promise.resolve(undefined); - } - - private loadFile(): Promise { - return this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) - .then(content => this.appendedMessage ? content.value + this.appendedMessage : content.value); - } - - protected updateModel(): void { - if (this.model && this.appendedMessage) { - this.appendToModel(this.appendedMessage); - this.appendedMessage = ''; - } - } - - private onFileChangedInOutputDirector(eventType: string, fileName?: string): void { - // Check if rotating file has changed. It changes only when the main file exceeds its limit. - if (this.rotatingFilePath === fileName) { - this.resettingDelayer.trigger(() => this.resetModel()); - } - } - - private write(content: string): void { - this.appender.append(content); - } - - private flush(): void { - this.appender.flush(); - } -} - -class OutputFileListener extends Disposable { - - private readonly _onDidContentChange = new Emitter(); - readonly onDidContentChange: Event = this._onDidContentChange.event; - - private watching: boolean = false; - private syncDelayer: ThrottledDelayer; - private etag: string | undefined; - - constructor( - private readonly file: URI, - private readonly fileService: IFileService - ) { - super(); - this.syncDelayer = new ThrottledDelayer(500); - } - - watch(eTag: string | undefined): void { - if (!this.watching) { - this.etag = eTag; - this.poll(); - this.watching = true; - } - } - - private poll(): void { - const loop = () => this.doWatch().then(() => this.poll()); - this.syncDelayer.trigger(loop); - } - - private doWatch(): Promise { - return this.fileService.resolveFile(this.file) - .then(stat => { - if (stat.etag !== this.etag) { - this.etag = stat.etag; - this._onDidContentChange.fire(stat.size); - } - }); - } - - unwatch(): void { - if (this.watching) { - this.syncDelayer.cancel(); - this.watching = false; - } - } - - dispose(): void { - this.unwatch(); - super.dispose(); - } -} - -/** - * An output channel driven by a file and does not support appending messages. - */ -class FileOutputChannel extends AbstractFileOutputChannel implements OutputChannel { - - private readonly fileHandler: OutputFileListener; - - private updateInProgress: boolean = false; - private etag: string | undefined = ''; - private loadModelPromise: Promise | null = null; - - constructor( - outputChannelDescriptor: IFileOutputChannelDescriptor, - modelUri: URI, - @IFileService fileService: IFileService, - @IModelService modelService: IModelService, - @IModeService modeService: IModeService - ) { - super(outputChannelDescriptor, modelUri, fileService, modelService, modeService); - - this.fileHandler = this._register(new OutputFileListener(this.file, this.fileService)); - this._register(this.fileHandler.onDidContentChange(size => this.update(size))); - this._register(toDisposable(() => this.fileHandler.unwatch())); - } - - loadModel(): Promise { - this.loadModelPromise = this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) - .then(content => { - this.endOffset = this.startOffset + Buffer.from(content.value).byteLength; - this.etag = content.etag; - return this.createModel(content.value); - }); - return this.loadModelPromise; - } - - clear(till?: number): void { - const loadModelPromise: Promise = this.loadModelPromise ? this.loadModelPromise : Promise.resolve(); - loadModelPromise.then(() => { - super.clear(till); - this.update(); - }); - } - - append(message: string): void { - throw new Error('Not supported'); - } - - protected updateModel(): void { - if (this.model) { - this.fileService.resolveContent(this.file, { position: this.endOffset, encoding: 'utf8' }) - .then(content => { - this.etag = content.etag; - if (content.value) { - this.endOffset = this.endOffset + Buffer.from(content.value).byteLength; - this.appendToModel(content.value); - } - this.updateInProgress = false; - }, () => this.updateInProgress = false); - } else { - this.updateInProgress = false; - } - } - - protected onModelCreated(model: ITextModel): void { - this.fileHandler.watch(this.etag); - } - - protected onModelWillDispose(model: ITextModel | null): void { - this.fileHandler.unwatch(); - } - - protected onUpdateModelCancelled(): void { - this.updateInProgress = false; - } - - update(size?: number): void { - if (this.model) { - if (!this.updateInProgress) { - this.updateInProgress = true; - if (isNumber(size) && this.endOffset > size) { // Reset - Content is removed - this.startOffset = this.endOffset = 0; - this.model.setValue(''); - } - this.modelUpdater.schedule(); - } - } - } -} - -export class OutputService extends Disposable implements IOutputService, ITextModelContentProvider { - - public _serviceBrand: any; - - private channels: Map = new Map(); - private activeChannelIdInStorage: string; - private activeChannel: IOutputChannel | null; - private readonly outputDir: string; - - private readonly _onActiveOutputChannel = new Emitter(); - readonly onActiveOutputChannel: Event = this._onActiveOutputChannel.event; - - private _outputPanel: OutputPanel; - - constructor( - @IStorageService private readonly storageService: IStorageService, - @IInstantiationService private readonly instantiationService: IInstantiationService, - @IPanelService private readonly panelService: IPanelService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @ITextModelService textModelResolverService: ITextModelService, - @IEnvironmentService environmentService: IEnvironmentService, - @IWindowService windowService: IWindowService, - @ILogService private readonly logService: ILogService, - @ITelemetryService private readonly telemetryService: ITelemetryService, - @ILifecycleService private readonly lifecycleService: ILifecycleService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - ) { - super(); - this.activeChannelIdInStorage = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, ''); - this.outputDir = join(environmentService.logsPath, `output_${windowService.getCurrentWindowId()}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`); - - // Register as text model content provider for output - textModelResolverService.registerTextModelContentProvider(OUTPUT_SCHEME, this); - instantiationService.createInstance(OutputLinkProvider); - - // Create output channels for already registered channels - const registry = Registry.as(Extensions.OutputChannels); - for (const channelIdentifier of registry.getChannels()) { - this.onDidRegisterChannel(channelIdentifier.id); - } - this._register(registry.onDidRegisterChannel(this.onDidRegisterChannel, this)); - - this._register(panelService.onDidPanelOpen(({ panel, focus }) => this.onDidPanelOpen(panel, !focus), this)); - this._register(panelService.onDidPanelClose(this.onDidPanelClose, this)); - - // Set active channel to first channel if not set - if (!this.activeChannel) { - const channels = this.getChannelDescriptors(); - this.activeChannel = channels && channels.length > 0 ? this.getChannel(channels[0].id) : null; - } - - this._register(this.lifecycleService.onShutdown(() => this.dispose())); - this._register(this.storageService.onWillSaveState(() => this.saveState())); - } - - provideTextContent(resource: URI): Promise | null { - const channel = this.getChannel(resource.path); - if (channel) { - return channel.loadModel(); - } - return null; - } - - showChannel(id: string, preserveFocus?: boolean): Promise { - const channel = this.getChannel(id); - if (!channel || this.isChannelShown(channel)) { - if (this._outputPanel && !preserveFocus) { - this._outputPanel.focus(); - } - return Promise.resolve(undefined); - } - - this.activeChannel = channel; - let promise: Promise; - if (this.isPanelShown()) { - promise = this.doShowChannel(channel, !!preserveFocus); - } else { - this.panelService.openPanel(OUTPUT_PANEL_ID); - promise = this.doShowChannel(this.activeChannel, !!preserveFocus); - } - return promise.then(() => this._onActiveOutputChannel.fire(id)); - } - - getChannel(id: string): IOutputChannel | null { - return this.channels.get(id) || null; - } - - getChannelDescriptors(): IOutputChannelDescriptor[] { - return Registry.as(Extensions.OutputChannels).getChannels(); - } - - getActiveChannel(): IOutputChannel | null { - return this.activeChannel; - } - - private onDidRegisterChannel(channelId: string): void { - const channel = this.createChannel(channelId); - this.channels.set(channelId, channel); - if (this.activeChannelIdInStorage === channelId) { - this.activeChannel = channel; - this.onDidPanelOpen(this.panelService.getActivePanel(), true) - .then(() => this._onActiveOutputChannel.fire(channelId)); - } - } - - private onDidPanelOpen(panel: IPanel | null, preserveFocus: boolean): Promise { - if (panel && panel.getId() === OUTPUT_PANEL_ID) { - this._outputPanel = this.panelService.getActivePanel(); - if (this.activeChannel) { - return this.doShowChannel(this.activeChannel, preserveFocus); - } - } - return Promise.resolve(undefined); - } - - private onDidPanelClose(panel: IPanel): void { - if (this._outputPanel && panel.getId() === OUTPUT_PANEL_ID) { - CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(false); - this._outputPanel.clearInput(); - } - } - - private createChannel(id: string): OutputChannel { - const channelDisposables: IDisposable[] = []; - const channel = this.instantiateChannel(id); - channel.onDidAppendedContent(() => { - if (!channel.scrollLock) { - const panel = this.panelService.getActivePanel(); - if (panel && panel.getId() === OUTPUT_PANEL_ID && this.isChannelShown(channel)) { - let outputPanel = panel; - outputPanel.revealLastLine(); - } - } - }, channelDisposables); - channel.onDispose(() => { - if (this.activeChannel === channel) { - const channels = this.getChannelDescriptors(); - const channel = channels.length ? this.getChannel(channels[0].id) : null; - if (channel && this.isPanelShown()) { - this.showChannel(channel.id, true); - } else { - this.activeChannel = channel; - if (this.activeChannel) { - this._onActiveOutputChannel.fire(this.activeChannel.id); - } - } - } - Registry.as(Extensions.OutputChannels).removeChannel(id); - dispose(channelDisposables); - }, channelDisposables); - - return channel; - } - - private instantiateChannel(id: string): OutputChannel { - const channelData = Registry.as(Extensions.OutputChannels).getChannel(id); - if (!channelData) { - this.logService.error(`Channel '${id}' is not registered yet`); - throw new Error(`Channel '${id}' is not registered yet`); - } - - const uri = URI.from({ scheme: OUTPUT_SCHEME, path: id }); - if (channelData && channelData.file) { - return this.instantiationService.createInstance(FileOutputChannel, channelData, uri); - } - try { - const channelDescriptor: IFileOutputChannelDescriptor = { id, label: channelData ? channelData.label : '', log: false, file: URI.file(join(this.outputDir, `${id}.log`)) }; - return this.instantiationService.createInstance(OutputChannelBackedByFile, channelDescriptor, uri); - } catch (e) { - // Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883) - this.logService.error(e); - /* __GDPR__ - "output.channel.creation.error" : {} - */ - this.telemetryService.publicLog('output.channel.creation.error'); - return this.instantiationService.createInstance(BufferredOutputChannel, { id, label: channelData ? channelData.label : '' }); - } - } - - private doShowChannel(channel: IOutputChannel, preserveFocus: boolean): Promise { - if (this._outputPanel) { - CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(channel instanceof FileOutputChannel && channel.outputChannelDescriptor.log); - return this._outputPanel.setInput(this.createInput(channel), EditorOptions.create({ preserveFocus }), CancellationToken.None) - .then(() => { - if (!preserveFocus) { - this._outputPanel.focus(); - } - }); - } - return Promise.resolve(undefined); - } - - private isChannelShown(channel: IOutputChannel): boolean { - return this.isPanelShown() && this.activeChannel === channel; - } - - private isPanelShown(): boolean { - const panel = this.panelService.getActivePanel(); - return !!panel && panel.getId() === OUTPUT_PANEL_ID; - } - - private createInput(channel: IOutputChannel): ResourceEditorInput { - const resource = URI.from({ scheme: OUTPUT_SCHEME, path: channel.id }); - return this.instantiationService.createInstance(ResourceEditorInput, nls.localize('output', "{0} - Output", channel.label), nls.localize('channel', "Output channel for '{0}'", channel.label), resource); - } - - private saveState(): void { - if (this.activeChannel) { - this.storageService.store(OUTPUT_ACTIVE_CHANNEL_KEY, this.activeChannel.id, StorageScope.WORKSPACE); - } - } -} - -export class LogContentProvider { - - private channels: Map = new Map(); - - constructor( - @IOutputService private readonly outputService: IOutputService, - @IInstantiationService private readonly instantiationService: IInstantiationService - ) { - } - - provideTextContent(resource: URI): Promise | null { - if (resource.scheme === LOG_SCHEME) { - let channel = this.getChannel(resource); - if (channel) { - return channel.loadModel(); - } - } - return null; - } - - private getChannel(resource: URI): OutputChannel | undefined { - const channelId = resource.path; - let channel = this.channels.get(channelId); - if (!channel) { - const channelDisposables: IDisposable[] = []; - const outputChannelDescriptor = this.outputService.getChannelDescriptors().filter(({ id }) => id === channelId)[0]; - if (outputChannelDescriptor && outputChannelDescriptor.file) { - channel = this.instantiationService.createInstance(FileOutputChannel, outputChannelDescriptor, resource); - channel.onDispose(() => dispose(channelDisposables), channelDisposables); - this.channels.set(channelId, channel); - } - } - return channel; - } -} -// Remove this channel when https://github.com/Microsoft/vscode/issues/47883 is fixed -class BufferredOutputChannel extends Disposable implements OutputChannel { - - readonly id: string; - readonly label: string; - readonly file: URI | null = null; - scrollLock: boolean = false; - - protected _onDidAppendedContent = new Emitter(); - readonly onDidAppendedContent: Event = this._onDidAppendedContent.event; - - private readonly _onDispose = new Emitter(); - readonly onDispose: Event = this._onDispose.event; - - private modelUpdater: RunOnceScheduler; - private model: ITextModel | null; - private readonly bufferredContent: BufferedContent; - private lastReadId: number | undefined = undefined; - - constructor( - protected readonly outputChannelIdentifier: IOutputChannelDescriptor, - @IModelService private readonly modelService: IModelService, - @IModeService private readonly modeService: IModeService - ) { - super(); - - this.id = outputChannelIdentifier.id; - this.label = outputChannelIdentifier.label; - - this.modelUpdater = new RunOnceScheduler(() => this.updateModel(), 300); - this._register(toDisposable(() => this.modelUpdater.cancel())); - - this.bufferredContent = new BufferedContent(); - this._register(toDisposable(() => this.bufferredContent.clear())); - } - - append(output: string) { - this.bufferredContent.append(output); - if (!this.modelUpdater.isScheduled()) { - this.modelUpdater.schedule(); - } - } - - update(): void { } - - clear(): void { - if (this.modelUpdater.isScheduled()) { - this.modelUpdater.cancel(); - } - if (this.model) { - this.model.setValue(''); - } - this.bufferredContent.clear(); - this.lastReadId = undefined; - } - - loadModel(): Promise { - const { value, id } = this.bufferredContent.getDelta(this.lastReadId); - if (this.model) { - this.model.setValue(value); - } else { - this.model = this.createModel(value); - } - this.lastReadId = id; - return Promise.resolve(this.model); - } - - private createModel(content: string): ITextModel { - const model = this.modelService.createModel(content, this.modeService.create(OUTPUT_MIME), URI.from({ scheme: OUTPUT_SCHEME, path: this.id })); - const disposables: IDisposable[] = []; - disposables.push(model.onWillDispose(() => { - this.model = null; - dispose(disposables); - })); - return model; - } - - private updateModel(): void { - if (this.model) { - const { value, id } = this.bufferredContent.getDelta(this.lastReadId); - this.lastReadId = id; - const lastLine = this.model.getLineCount(); - const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine); - this.model.applyEdits([EditOperation.insert(new Position(lastLine, lastLineMaxColumn), value)]); - this._onDidAppendedContent.fire(); - } - } - - dispose(): void { - this._onDispose.fire(); - super.dispose(); - } -} - -class BufferedContent { - - private data: string[] = []; - private dataIds: number[] = []; - private idPool = 0; - private length = 0; - - public append(content: string): void { - this.data.push(content); - this.dataIds.push(++this.idPool); - this.length += content.length; - this.trim(); - } - - public clear(): void { - this.data.length = 0; - this.dataIds.length = 0; - this.length = 0; - } - - private trim(): void { - if (this.length < MAX_OUTPUT_LENGTH * 1.2) { - return; - } - - while (this.length > MAX_OUTPUT_LENGTH) { - this.dataIds.shift(); - const removed = this.data.shift(); - if (removed) { - this.length -= removed.length; - } - } - } - - public getDelta(previousId?: number): { value: string, id: number } { - let idx = -1; - if (previousId !== undefined) { - idx = binarySearch(this.dataIds, previousId, (a, b) => a - b); - } - - const id = this.idPool; - if (idx >= 0) { - const value = strings.removeAnsiEscapeCodes(this.data.slice(idx + 1).join('')); - return { value, id }; - } else { - const value = strings.removeAnsiEscapeCodes(this.data.join('')); - return { value, id }; - } - } -} diff --git a/src/vs/workbench/services/output/common/outputChannelModel.ts b/src/vs/workbench/services/output/common/outputChannelModel.ts new file mode 100644 index 00000000000..aabcd3ffc54 --- /dev/null +++ b/src/vs/workbench/services/output/common/outputChannelModel.ts @@ -0,0 +1,413 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import * as strings from 'vs/base/common/strings'; +import { ITextModel } from 'vs/editor/common/model'; +import { Emitter, Event } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; +import { RunOnceScheduler, ThrottledDelayer } from 'vs/base/common/async'; +import { IFileService } from 'vs/platform/files/common/files'; +import { IModelService } from 'vs/editor/common/services/modelService'; +import { IModeService } from 'vs/editor/common/services/modeService'; +import { Disposable, toDisposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { isNumber } from 'vs/base/common/types'; +import { EditOperation } from 'vs/editor/common/core/editOperation'; +import { Position } from 'vs/editor/common/core/position'; +import { binarySearch } from 'vs/base/common/arrays'; + +export interface IOutputChannelModel extends IDisposable { + readonly onDidAppendedContent: Event; + readonly onDispose: Event; + append(output: string): void; + update(): void; + loadModel(): Promise; + clear(till?: number): void; +} + +export const IOutputChannelModelService = createDecorator('outputChannelModelService'); + +export interface IOutputChannelModelService { + _serviceBrand: any; + + createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel; + +} + +export abstract class AsbtractOutputChannelModelService { + + constructor( + @IInstantiationService protected readonly instantiationService: IInstantiationService + ) { } + + createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel { + return file ? this.instantiationService.createInstance(FileOutputChannelModel, modelUri, mimeType, file) : this.instantiationService.createInstance(BufferredOutputChannel, modelUri, mimeType); + } + +} + +export abstract class AbstractFileOutputChannelModel extends Disposable implements IOutputChannelModel { + + protected _onDidAppendedContent = new Emitter(); + readonly onDidAppendedContent: Event = this._onDidAppendedContent.event; + + protected _onDispose = new Emitter(); + readonly onDispose: Event = this._onDispose.event; + + protected modelUpdater: RunOnceScheduler; + protected model: ITextModel | null; + + protected startOffset: number = 0; + protected endOffset: number = 0; + + constructor( + private readonly modelUri: URI, + private readonly mimeType: string, + protected readonly file: URI, + protected fileService: IFileService, + protected modelService: IModelService, + protected modeService: IModeService, + ) { + super(); + this.modelUpdater = new RunOnceScheduler(() => this.updateModel(), 300); + this._register(toDisposable(() => this.modelUpdater.cancel())); + } + + clear(till?: number): void { + if (this.modelUpdater.isScheduled()) { + this.modelUpdater.cancel(); + this.onUpdateModelCancelled(); + } + if (this.model) { + this.model.setValue(''); + } + this.endOffset = isNumber(till) ? till : this.endOffset; + this.startOffset = this.endOffset; + } + + update(): void { } + + protected createModel(content: string): ITextModel { + if (this.model) { + this.model.setValue(content); + } else { + this.model = this.modelService.createModel(content, this.modeService.create(this.mimeType), this.modelUri); + this.onModelCreated(this.model); + const disposables: IDisposable[] = []; + disposables.push(this.model.onWillDispose(() => { + this.onModelWillDispose(this.model); + this.model = null; + dispose(disposables); + })); + } + return this.model; + } + + appendToModel(content: string): void { + if (this.model && content) { + const lastLine = this.model.getLineCount(); + const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine); + this.model.applyEdits([EditOperation.insert(new Position(lastLine, lastLineMaxColumn), content)]); + this._onDidAppendedContent.fire(); + } + } + + abstract loadModel(): Promise; + abstract append(message: string); + + protected onModelCreated(model: ITextModel) { } + protected onModelWillDispose(model: ITextModel | null) { } + protected onUpdateModelCancelled() { } + protected updateModel() { } + + dispose(): void { + this._onDispose.fire(); + super.dispose(); + } +} + +class OutputFileListener extends Disposable { + + private readonly _onDidContentChange = new Emitter(); + readonly onDidContentChange: Event = this._onDidContentChange.event; + + private watching: boolean = false; + private syncDelayer: ThrottledDelayer; + private etag: string | undefined; + + constructor( + private readonly file: URI, + private readonly fileService: IFileService + ) { + super(); + this.syncDelayer = new ThrottledDelayer(500); + } + + watch(eTag: string | undefined): void { + if (!this.watching) { + this.etag = eTag; + this.poll(); + this.watching = true; + } + } + + private poll(): void { + const loop = () => this.doWatch().then(() => this.poll()); + this.syncDelayer.trigger(loop); + } + + private doWatch(): Promise { + return this.fileService.resolveFile(this.file) + .then(stat => { + if (stat.etag !== this.etag) { + this.etag = stat.etag; + this._onDidContentChange.fire(stat.size); + } + }); + } + + unwatch(): void { + if (this.watching) { + this.syncDelayer.cancel(); + this.watching = false; + } + } + + dispose(): void { + this.unwatch(); + super.dispose(); + } +} + +/** + * An output channel driven by a file and does not support appending messages. + */ +export class FileOutputChannelModel extends AbstractFileOutputChannelModel implements IOutputChannelModel { + + private readonly fileHandler: OutputFileListener; + + private updateInProgress: boolean = false; + private etag: string | undefined = ''; + private loadModelPromise: Promise | null = null; + + constructor( + modelUri: URI, + mimeType: string, + file: URI, + @IFileService fileService: IFileService, + @IModelService modelService: IModelService, + @IModeService modeService: IModeService + ) { + super(modelUri, mimeType, file, fileService, modelService, modeService); + + this.fileHandler = this._register(new OutputFileListener(this.file, this.fileService)); + this._register(this.fileHandler.onDidContentChange(size => this.update(size))); + this._register(toDisposable(() => this.fileHandler.unwatch())); + } + + loadModel(): Promise { + this.loadModelPromise = this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) + .then(content => { + this.endOffset = this.startOffset + Buffer.from(content.value).byteLength; + this.etag = content.etag; + return this.createModel(content.value); + }); + return this.loadModelPromise; + } + + clear(till?: number): void { + const loadModelPromise: Promise = this.loadModelPromise ? this.loadModelPromise : Promise.resolve(); + loadModelPromise.then(() => { + super.clear(till); + this.update(); + }); + } + + append(message: string): void { + throw new Error('Not supported'); + } + + protected updateModel(): void { + if (this.model) { + this.fileService.resolveContent(this.file, { position: this.endOffset, encoding: 'utf8' }) + .then(content => { + this.etag = content.etag; + if (content.value) { + this.endOffset = this.endOffset + Buffer.from(content.value).byteLength; + this.appendToModel(content.value); + } + this.updateInProgress = false; + }, () => this.updateInProgress = false); + } else { + this.updateInProgress = false; + } + } + + protected onModelCreated(model: ITextModel): void { + this.fileHandler.watch(this.etag); + } + + protected onModelWillDispose(model: ITextModel | null): void { + this.fileHandler.unwatch(); + } + + protected onUpdateModelCancelled(): void { + this.updateInProgress = false; + } + + update(size?: number): void { + if (this.model) { + if (!this.updateInProgress) { + this.updateInProgress = true; + if (isNumber(size) && this.endOffset > size) { // Reset - Content is removed + this.startOffset = this.endOffset = 0; + this.model.setValue(''); + } + this.modelUpdater.schedule(); + } + } + } +} + +class BufferredOutputChannel extends Disposable implements IOutputChannelModel { + + readonly file: URI | null = null; + scrollLock: boolean = false; + + protected _onDidAppendedContent = new Emitter(); + readonly onDidAppendedContent: Event = this._onDidAppendedContent.event; + + private readonly _onDispose = new Emitter(); + readonly onDispose: Event = this._onDispose.event; + + private modelUpdater: RunOnceScheduler; + private model: ITextModel | null; + private readonly bufferredContent: BufferedContent; + private lastReadId: number | undefined = undefined; + + constructor( + private readonly modelUri: URI, private readonly mimeType: string, + @IModelService private readonly modelService: IModelService, + @IModeService private readonly modeService: IModeService + ) { + super(); + + this.modelUpdater = new RunOnceScheduler(() => this.updateModel(), 300); + this._register(toDisposable(() => this.modelUpdater.cancel())); + + this.bufferredContent = new BufferedContent(); + this._register(toDisposable(() => this.bufferredContent.clear())); + } + + append(output: string) { + this.bufferredContent.append(output); + if (!this.modelUpdater.isScheduled()) { + this.modelUpdater.schedule(); + } + } + + update(): void { } + + clear(): void { + if (this.modelUpdater.isScheduled()) { + this.modelUpdater.cancel(); + } + if (this.model) { + this.model.setValue(''); + } + this.bufferredContent.clear(); + this.lastReadId = undefined; + } + + loadModel(): Promise { + const { value, id } = this.bufferredContent.getDelta(this.lastReadId); + if (this.model) { + this.model.setValue(value); + } else { + this.model = this.createModel(value); + } + this.lastReadId = id; + return Promise.resolve(this.model); + } + + private createModel(content: string): ITextModel { + const model = this.modelService.createModel(content, this.modeService.create(this.mimeType), this.modelUri); + const disposables: IDisposable[] = []; + disposables.push(model.onWillDispose(() => { + this.model = null; + dispose(disposables); + })); + return model; + } + + private updateModel(): void { + if (this.model) { + const { value, id } = this.bufferredContent.getDelta(this.lastReadId); + this.lastReadId = id; + const lastLine = this.model.getLineCount(); + const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine); + this.model.applyEdits([EditOperation.insert(new Position(lastLine, lastLineMaxColumn), value)]); + this._onDidAppendedContent.fire(); + } + } + + dispose(): void { + this._onDispose.fire(); + super.dispose(); + } +} + +class BufferedContent { + + private static MAX_OUTPUT_LENGTH = 10000 /* Max. number of output lines to show in output */ * 100 /* Guestimated chars per line */; + + private data: string[] = []; + private dataIds: number[] = []; + private idPool = 0; + private length = 0; + + public append(content: string): void { + this.data.push(content); + this.dataIds.push(++this.idPool); + this.length += content.length; + this.trim(); + } + + public clear(): void { + this.data.length = 0; + this.dataIds.length = 0; + this.length = 0; + } + + private trim(): void { + if (this.length < BufferedContent.MAX_OUTPUT_LENGTH * 1.2) { + return; + } + + while (this.length > BufferedContent.MAX_OUTPUT_LENGTH) { + this.dataIds.shift(); + const removed = this.data.shift(); + if (removed) { + this.length -= removed.length; + } + } + } + + public getDelta(previousId?: number): { value: string, id: number } { + let idx = -1; + if (previousId !== undefined) { + idx = binarySearch(this.dataIds, previousId, (a, b) => a - b); + } + + const id = this.idPool; + if (idx >= 0) { + const value = strings.removeAnsiEscapeCodes(this.data.slice(idx + 1).join('')); + return { value, id }; + } else { + const value = strings.removeAnsiEscapeCodes(this.data.join('')); + return { value, id }; + } + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/output/common/outputChannelModelService.ts b/src/vs/workbench/services/output/common/outputChannelModelService.ts new file mode 100644 index 00000000000..6aceb81e99e --- /dev/null +++ b/src/vs/workbench/services/output/common/outputChannelModelService.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IOutputChannelModelService, AsbtractOutputChannelModelService } from 'vs/workbench/services/output/common/outputChannelModel'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; + +export class OutputChannelModelService extends AsbtractOutputChannelModelService implements IOutputChannelModelService { + _serviceBrand: any; +} + +registerSingleton(IOutputChannelModelService, OutputChannelModelService); + diff --git a/src/vs/workbench/contrib/output/node/outputAppender.ts b/src/vs/workbench/services/output/node/outputAppender.ts similarity index 100% rename from src/vs/workbench/contrib/output/node/outputAppender.ts rename to src/vs/workbench/services/output/node/outputAppender.ts diff --git a/src/vs/workbench/services/output/node/outputChannelModelService.ts b/src/vs/workbench/services/output/node/outputChannelModelService.ts new file mode 100644 index 00000000000..7709518de6f --- /dev/null +++ b/src/vs/workbench/services/output/node/outputChannelModelService.ts @@ -0,0 +1,192 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import * as extfs from 'vs/base/node/extfs'; +import { dirname, join } from 'vs/base/common/path'; +import { ITextModel } from 'vs/editor/common/model'; +import { URI } from 'vs/base/common/uri'; +import { ThrottledDelayer } from 'vs/base/common/async'; +import { IFileService } from 'vs/platform/files/common/files'; +import { IModelService } from 'vs/editor/common/services/modelService'; +import { IModeService } from 'vs/editor/common/services/modeService'; +import { toDisposable, IDisposable } from 'vs/base/common/lifecycle'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IOutputChannelModel, AbstractFileOutputChannelModel, IOutputChannelModelService, AsbtractOutputChannelModelService } from 'vs/workbench/services/output/common/outputChannelModel'; +import { OutputAppender } from 'vs/workbench/services/output/node/outputAppender'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { toLocalISOString } from 'vs/base/common/date'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; + +let watchingOutputDir = false; +let callbacks: ((eventType: string, fileName?: string) => void)[] = []; +function watchOutputDirectory(outputDir: string, logService: ILogService, onChange: (eventType: string, fileName: string) => void): IDisposable { + callbacks.push(onChange); + if (!watchingOutputDir) { + const watcherDisposable = extfs.watch(outputDir, (eventType, fileName) => { + for (const callback of callbacks) { + callback(eventType, fileName); + } + }, (error: string) => { + logService.error(error); + }); + watchingOutputDir = true; + return toDisposable(() => { + callbacks = []; + watcherDisposable.dispose(); + }); + } + return toDisposable(() => { }); +} + +class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implements IOutputChannelModel { + + private appender: OutputAppender; + private appendedMessage: string; + private loadingFromFileInProgress: boolean; + private resettingDelayer: ThrottledDelayer; + private readonly rotatingFilePath: string; + + constructor( + id: string, + modelUri: URI, + mimeType: string, + @IWindowService windowService: IWindowService, + @IEnvironmentService environmentService: IEnvironmentService, + @IFileService fileService: IFileService, + @IModelService modelService: IModelService, + @IModeService modeService: IModeService, + @ILogService logService: ILogService + ) { + const outputDir = join(environmentService.logsPath, `output_${windowService.getCurrentWindowId()}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`); + super(modelUri, mimeType, URI.file(join(outputDir, `${id}.log`)), fileService, modelService, modeService); + this.appendedMessage = ''; + this.loadingFromFileInProgress = false; + + // Use one rotating file to check for main file reset + this.appender = new OutputAppender(id, this.file.fsPath); + this.rotatingFilePath = `${id}.1.log`; + this._register(watchOutputDirectory(dirname(this.file.fsPath), logService, (eventType, file) => this.onFileChangedInOutputDirector(eventType, file))); + + this.resettingDelayer = new ThrottledDelayer(50); + } + + append(message: string): void { + // update end offset always as message is read + this.endOffset = this.endOffset + Buffer.from(message).byteLength; + if (this.loadingFromFileInProgress) { + this.appendedMessage += message; + } else { + this.write(message); + if (this.model) { + this.appendedMessage += message; + if (!this.modelUpdater.isScheduled()) { + this.modelUpdater.schedule(); + } + } + } + } + + clear(till?: number): void { + super.clear(till); + this.appendedMessage = ''; + } + + loadModel(): Promise { + this.loadingFromFileInProgress = true; + if (this.modelUpdater.isScheduled()) { + this.modelUpdater.cancel(); + } + this.appendedMessage = ''; + return this.loadFile() + .then(content => { + if (this.endOffset !== this.startOffset + Buffer.from(content).byteLength) { + // Queue content is not written into the file + // Flush it and load file again + this.flush(); + return this.loadFile(); + } + return content; + }) + .then(content => { + if (this.appendedMessage) { + this.write(this.appendedMessage); + this.appendedMessage = ''; + } + this.loadingFromFileInProgress = false; + return this.createModel(content); + }); + } + + private resetModel(): Promise { + this.startOffset = 0; + this.endOffset = 0; + if (this.model) { + return this.loadModel().then(() => undefined); + } + return Promise.resolve(undefined); + } + + private loadFile(): Promise { + return this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) + .then(content => this.appendedMessage ? content.value + this.appendedMessage : content.value); + } + + protected updateModel(): void { + if (this.model && this.appendedMessage) { + this.appendToModel(this.appendedMessage); + this.appendedMessage = ''; + } + } + + private onFileChangedInOutputDirector(eventType: string, fileName?: string): void { + // Check if rotating file has changed. It changes only when the main file exceeds its limit. + if (this.rotatingFilePath === fileName) { + this.resettingDelayer.trigger(() => this.resetModel()); + } + } + + private write(content: string): void { + this.appender.append(content); + } + + private flush(): void { + this.appender.flush(); + } +} + +export class OutputChannelModelService extends AsbtractOutputChannelModelService implements IOutputChannelModelService { + + _serviceBrand: any; + + constructor( + @IInstantiationService instantiationService: IInstantiationService, + @ILogService private readonly logService: ILogService, + @ITelemetryService private readonly telemetryService: ITelemetryService + ) { + super(instantiationService); + } + + createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel { + if (!file) { + try { + return this.instantiationService.createInstance(OutputChannelBackedByFile, id, modelUri, mimeType); + } catch (e) { + // Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883) + this.logService.error(e); + /* __GDPR__ + "output.channel.creation.error" : {} + */ + this.telemetryService.publicLog('output.channel.creation.error'); + } + } + return super.createOutputChannelModel(id, modelUri, mimeType, file); + } + +} + +registerSingleton(IOutputChannelModelService, OutputChannelModelService); diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index d8bf039ff5d..af9408a8051 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -69,6 +69,7 @@ import 'vs/workbench/services/progress/browser/progressService2'; import 'vs/workbench/services/editor/browser/codeEditorService'; import 'vs/workbench/services/broadcast/electron-browser/broadcastService'; import 'vs/workbench/services/preferences/browser/preferencesService'; +import 'vs/workbench/services/output/node/outputChannelModelService'; import 'vs/workbench/services/configuration/node/jsonEditingService'; import 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import 'vs/workbench/services/textfile/common/textFileService'; @@ -155,7 +156,7 @@ import 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen'; import 'vs/workbench/contrib/extensions/electron-browser/extensionsViewlet'; // Output Panel -import 'vs/workbench/contrib/output/electron-browser/output.contribution'; +import 'vs/workbench/contrib/output/browser/output.contribution'; import 'vs/workbench/contrib/output/browser/outputPanel'; // Terminal From e80300adbe5ae37f05c28ebda9ef05652d6d67fc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 6 Mar 2019 11:57:57 -0800 Subject: [PATCH 170/172] Auto let -> const and auto mark privates as readonly in vs/code --- .../issue/issueReporterMain.ts | 4 +-- .../issue/issueReporterModel.ts | 6 ++-- .../contrib/languagePackCachedDataCleaner.ts | 6 ++-- src/vs/code/electron-main/app.ts | 12 +++---- src/vs/code/electron-main/window.ts | 4 +-- src/vs/code/electron-main/windows.ts | 32 +++++++++---------- src/vs/code/node/cliProcessMain.ts | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index ca5ed69d0af..c4d6e66aaa8 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -64,14 +64,14 @@ export class IssueReporter extends Disposable { private environmentService: IEnvironmentService; private telemetryService: ITelemetryService; private logService: ILogService; - private issueReporterModel: IssueReporterModel; + private readonly issueReporterModel: IssueReporterModel; private numberOfSearchResultsDisplayed = 0; private receivedSystemInfo = false; private receivedPerformanceInfo = false; private shouldQueueSearch = false; private hasBeenSubmitted = false; - private previewButton: Button; + private readonly previewButton: Button; constructor(configuration: IssueReporterConfiguration) { super(); diff --git a/src/vs/code/electron-browser/issue/issueReporterModel.ts b/src/vs/code/electron-browser/issue/issueReporterModel.ts index b918ceff961..8ad189c44b4 100644 --- a/src/vs/code/electron-browser/issue/issueReporterModel.ts +++ b/src/vs/code/electron-browser/issue/issueReporterModel.ts @@ -34,7 +34,7 @@ export interface IssueReporterData { } export class IssueReporterModel { - private _data: IssueReporterData; + private readonly _data: IssueReporterData; constructor(initialData?: Partial) { const defaultData = { @@ -196,7 +196,7 @@ ${this._data.workspaceInfo}; return 'Extensions: none' + themeExclusionStr; } - let tableHeader = `Extension|Author (truncated)|Version + const tableHeader = `Extension|Author (truncated)|Version ---|---|---`; const table = this._data.enabledNonThemeExtesions.map(e => { return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`; @@ -226,7 +226,7 @@ Literal matches: ${this._data.filterResultCount}`; return `No fuzzy results`; } - let tableHeader = `Setting|Extension|Score + const tableHeader = `Setting|Extension|Score ---|---|---`; const table = this._data.actualSearchResults.map(setting => { return `${setting.key}|${setting.extensionId}|${String(setting.score).slice(0, 5)}`; diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner.ts index 19c73491115..e7f1eec7742 100644 --- a/src/vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner.ts +++ b/src/vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner.ts @@ -57,15 +57,15 @@ export class LanguagePackCachedDataCleaner { ? 1000 * 60 * 60 * 24 * 7 // roughly 1 week : 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months try { - let installed: IStringDictionary = Object.create(null); + const installed: IStringDictionary = Object.create(null); const metaData: LanguagePackFile = JSON.parse(await pfs.readFile(path.join(this._environmentService.userDataPath, 'languagepacks.json'), 'utf8')); for (let locale of Object.keys(metaData)) { - let entry = metaData[locale]; + const entry = metaData[locale]; installed[`${entry.hash}.${locale}`] = true; } // Cleanup entries for language packs that aren't installed anymore const cacheDir = path.join(this._environmentService.userDataPath, 'clp'); - let exists = await pfs.exists(cacheDir); + const exists = await pfs.exists(cacheDir); if (!exists) { return; } diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index a97534eb331..d0e144be9fe 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -91,8 +91,8 @@ export class CodeApplication extends Disposable { private sharedProcessClient: Promise; constructor( - private mainIpcServer: Server, - private userEnv: IProcessEnvironment, + private readonly mainIpcServer: Server, + private readonly userEnv: IProcessEnvironment, @IInstantiationService private readonly instantiationService: IInstantiationService, @ILogService private readonly logService: ILogService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @@ -648,9 +648,9 @@ export class CodeApplication extends Disposable { const isBuilt = this.environmentService.isBuilt; class ActiveConnection { - private _authority: string; - private _client: Promise>; - private _disposeRunner: RunOnceScheduler; + private readonly _authority: string; + private readonly _client: Promise>; + private readonly _disposeRunner: RunOnceScheduler; constructor(authority: string, host: string, port: number) { this._authority = authority; @@ -707,7 +707,7 @@ export class CodeApplication extends Disposable { if (connectionPool.has(uri.authority)) { activeConnection = connectionPool.get(uri.authority); } else { - let resolvedAuthority = resolveAuthority(uri.authority); + const resolvedAuthority = resolveAuthority(uri.authority); if (!resolvedAuthority) { callback(undefined); return; diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index b63e759f3a9..234ed41eeb1 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -69,14 +69,14 @@ export class CodeWindow extends Disposable implements ICodeWindow { private currentMenuBarVisibility: MenuBarVisibility; private representedFilename: string; - private whenReadyCallbacks: { (window: ICodeWindow): void }[]; + private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[]; private currentConfig: IWindowConfiguration; private pendingLoadConfig?: IWindowConfiguration; private marketplaceHeadersPromise: Promise; - private touchBarGroups: Electron.TouchBarSegmentedControl[]; + private readonly touchBarGroups: Electron.TouchBarSegmentedControl[]; constructor( config: IWindowCreationOptions, diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index b3a582ce9c5..1bd75d43c0c 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -158,11 +158,11 @@ export class WindowsManager implements IWindowsMainService { private initialUserEnv: IProcessEnvironment; - private windowsState: IWindowsState; + private readonly windowsState: IWindowsState; private lastClosedWindowState?: IWindowState; - private dialogs: Dialogs; - private workspacesManager: WorkspacesManager; + private readonly dialogs: Dialogs; + private readonly workspacesManager: WorkspacesManager; private _onWindowReady = new Emitter(); onWindowReady: CommonEvent = this._onWindowReady.event; @@ -367,7 +367,7 @@ export class WindowsManager implements IWindowsMainService { this.logService.trace('windowsManager#open'); openConfig = this.validateOpenConfig(openConfig); - let pathsToOpen = this.getPathsToOpen(openConfig); + const pathsToOpen = this.getPathsToOpen(openConfig); const foldersToAdd: IFolderPathToOpen[] = []; const foldersToOpen: IFolderPathToOpen[] = []; @@ -439,7 +439,7 @@ export class WindowsManager implements IWindowsMainService { // Make sure to pass focus to the most relevant of the windows if we open multiple if (usedWindows.length > 1) { - let focusLastActive = this.windowsState.lastActiveWindow && !openConfig.forceEmpty && !hasArgs(openConfig.cli._) && !hasArgs(openConfig.cli['file-uri']) && !hasArgs(openConfig.cli['folder-uri']) && !(openConfig.urisToOpen && openConfig.urisToOpen.length); + const focusLastActive = this.windowsState.lastActiveWindow && !openConfig.forceEmpty && !hasArgs(openConfig.cli._) && !hasArgs(openConfig.cli['file-uri']) && !hasArgs(openConfig.cli['folder-uri']) && !(openConfig.urisToOpen && openConfig.urisToOpen.length); let focusLastOpened = true; let focusLastWindow = true; @@ -550,7 +550,7 @@ export class WindowsManager implements IWindowsMainService { // only look at the windows with correct authority const windows = WindowsManager.WINDOWS.filter(w => w.remoteAuthority === fileInputs!.remoteAuthority); - let bestWindowOrFolder = findBestWindowOrFolderForFile({ + const bestWindowOrFolder = findBestWindowOrFolderForFile({ windows, newWindow: openFilesInNewWindow, context: openConfig.context, @@ -819,7 +819,7 @@ export class WindowsManager implements IWindowsMainService { if (!openConfig.addMode && isCommandLineOrAPICall) { const foldersToOpen = windowsToOpen.filter(path => !!path.folderUri); if (foldersToOpen.length > 1) { - let remoteAuthority = foldersToOpen[0].remoteAuthority; + const remoteAuthority = foldersToOpen[0].remoteAuthority; if (foldersToOpen.every(f => f.remoteAuthority === remoteAuthority)) { // only if all folder have the same authority const workspace = this.workspacesMainService.createUntitledWorkspaceSync(foldersToOpen.map(folder => ({ uri: folder.folderUri! }))); @@ -836,7 +836,7 @@ export class WindowsManager implements IWindowsMainService { private doExtractPathsFromAPI(openConfig: IOpenConfiguration): IPathToOpen[] { const pathsToOpen: IPathToOpen[] = []; const cli = openConfig.cli; - let parseOptions: IPathParseOptions = { gotoLineMode: cli && cli.goto, forceOpenWorkspaceAsFile: openConfig.forceOpenWorkspaceAsFile }; + const parseOptions: IPathParseOptions = { gotoLineMode: cli && cli.goto, forceOpenWorkspaceAsFile: openConfig.forceOpenWorkspaceAsFile }; for (const pathToOpen of openConfig.urisToOpen || []) { if (!pathToOpen) { continue; @@ -979,7 +979,7 @@ export class WindowsManager implements IWindowsMainService { private argToUri(arg: string): URI | undefined { try { - let uri = URI.parse(arg); + const uri = URI.parse(arg); if (!uri.scheme) { this.logService.error(`Invalid URI input string, scheme missing: ${arg}`); return undefined; @@ -1547,7 +1547,7 @@ export class WindowsManager implements IWindowsMainService { openNewWindow(context: OpenContext, options?: INewWindowOptions): ICodeWindow[] { let cli = this.environmentService.args; - let remote = options && options.remoteAuthority || undefined; + const remote = options && options.remoteAuthority || undefined; if (cli && (cli.remote !== remote)) { cli = { ...cli, remote }; } @@ -1784,14 +1784,14 @@ class Dialogs { private static readonly workingDirPickerStorageKey = 'pickerWorkingDir'; - private mapWindowToDialogQueue: Map>; - private noWindowDialogQueue: Queue; + private readonly mapWindowToDialogQueue: Map>; + private readonly noWindowDialogQueue: Queue; constructor( - private environmentService: IEnvironmentService, - private telemetryService: ITelemetryService, - private stateService: IStateService, - private windowsMainService: IWindowsMainService, + private readonly environmentService: IEnvironmentService, + private readonly telemetryService: ITelemetryService, + private readonly stateService: IStateService, + private readonly windowsMainService: IWindowsMainService, ) { this.mapWindowToDialogQueue = new Map>(); this.noWindowDialogQueue = new Queue(); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 3f07a1e6365..566448022a8 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -104,7 +104,7 @@ export class Main { } private async installExtensions(extensions: string[], force: boolean): Promise { - let failed: string[] = []; + const failed: string[] = []; for (const extension of extensions) { try { await this.installExtension(extension, force); From d14eab580ee3fa124bf74610a53ef3413c082e94 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 6 Mar 2019 13:54:22 -0800 Subject: [PATCH 171/172] Auto let -> const in vs/editor Const is preferred for type guards --- .../editor/browser/config/charWidthReader.ts | 14 +-- src/vs/editor/browser/config/configuration.ts | 26 ++-- .../editor/browser/controller/coreCommands.ts | 24 ++-- .../editor/browser/controller/mouseHandler.ts | 68 +++++------ .../editor/browser/controller/mouseTarget.ts | 100 ++++++++-------- .../browser/controller/pointerHandler.ts | 24 ++-- .../browser/controller/textAreaState.ts | 26 ++-- src/vs/editor/browser/core/editorState.ts | 4 +- src/vs/editor/browser/editorDom.ts | 6 +- src/vs/editor/browser/editorExtensions.ts | 6 +- .../services/abstractCodeEditorService.ts | 2 +- .../browser/services/codeEditorServiceImpl.ts | 32 ++--- src/vs/editor/browser/view/viewController.ts | 2 +- src/vs/editor/browser/view/viewImpl.ts | 50 ++++---- src/vs/editor/browser/view/viewLayer.ts | 112 +++++++++--------- src/vs/editor/browser/view/viewOverlays.ts | 18 +-- src/vs/editor/browser/view/viewPart.ts | 4 +- .../contentWidgets/contentWidgets.ts | 54 ++++----- .../viewParts/decorations/decorations.ts | 34 +++--- .../editorScrollbar/editorScrollbar.ts | 12 +- .../viewParts/glyphMargin/glyphMargin.ts | 38 +++--- .../viewParts/indentGuides/indentGuides.ts | 8 +- .../viewParts/lineNumbers/lineNumbers.ts | 20 ++-- .../browser/viewParts/lines/rangeUtil.ts | 10 +- .../browser/viewParts/lines/viewLine.ts | 52 ++++---- .../browser/viewParts/lines/viewLines.ts | 94 +++++++-------- .../linesDecorations/linesDecorations.ts | 24 ++-- .../editor/browser/viewParts/margin/margin.ts | 4 +- .../marginDecorations/marginDecorations.ts | 18 +-- .../browser/viewParts/minimap/minimap.ts | 26 ++-- .../overlayWidgets/overlayWidgets.ts | 10 +- .../overviewRuler/decorationsOverviewRuler.ts | 2 +- .../viewParts/overviewRuler/overviewRuler.ts | 6 +- .../editor/browser/viewParts/rulers/rulers.ts | 6 +- .../scrollDecoration/scrollDecoration.ts | 2 +- .../viewParts/selections/selections.ts | 68 +++++------ .../viewParts/viewCursors/viewCursors.ts | 16 +-- .../browser/viewParts/viewZones/viewZones.ts | 38 +++--- .../editor/browser/widget/codeEditorWidget.ts | 110 ++++++++--------- src/vs/editor/common/modes.ts | 2 +- 40 files changed, 586 insertions(+), 586 deletions(-) diff --git a/src/vs/editor/browser/config/charWidthReader.ts b/src/vs/editor/browser/config/charWidthReader.ts index d24f7b5cf9b..a578ce29186 100644 --- a/src/vs/editor/browser/config/charWidthReader.ts +++ b/src/vs/editor/browser/config/charWidthReader.ts @@ -62,12 +62,12 @@ class DomCharWidthReader { } private _createDomElements(): void { - let container = document.createElement('div'); + const container = document.createElement('div'); container.style.position = 'absolute'; container.style.top = '-50000px'; container.style.width = '50000px'; - let regularDomNode = document.createElement('div'); + const regularDomNode = document.createElement('div'); regularDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); regularDomNode.style.fontWeight = this._bareFontInfo.fontWeight; regularDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; @@ -75,7 +75,7 @@ class DomCharWidthReader { regularDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px'; container.appendChild(regularDomNode); - let boldDomNode = document.createElement('div'); + const boldDomNode = document.createElement('div'); boldDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); boldDomNode.style.fontWeight = 'bold'; boldDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; @@ -83,7 +83,7 @@ class DomCharWidthReader { boldDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px'; container.appendChild(boldDomNode); - let italicDomNode = document.createElement('div'); + const italicDomNode = document.createElement('div'); italicDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily(); italicDomNode.style.fontWeight = this._bareFontInfo.fontWeight; italicDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px'; @@ -92,7 +92,7 @@ class DomCharWidthReader { italicDomNode.style.fontStyle = 'italic'; container.appendChild(italicDomNode); - let testElements: HTMLSpanElement[] = []; + const testElements: HTMLSpanElement[] = []; for (let i = 0, len = this._requests.length; i < len; i++) { const request = this._requests[i]; @@ -109,7 +109,7 @@ class DomCharWidthReader { parent!.appendChild(document.createElement('br')); - let testElement = document.createElement('span'); + const testElement = document.createElement('span'); DomCharWidthReader._render(testElement, request); parent!.appendChild(testElement); @@ -149,6 +149,6 @@ class DomCharWidthReader { } export function readCharWidths(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]): void { - let reader = new DomCharWidthReader(bareFontInfo, requests); + const reader = new DomCharWidthReader(bareFontInfo, requests); reader.read(); } diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 32e87b2a794..1a61fdfeb33 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -28,23 +28,23 @@ class CSSBasedConfigurationCache { } public has(item: BareFontInfo): boolean { - let itemId = item.getId(); + const itemId = item.getId(); return !!this._values[itemId]; } public get(item: BareFontInfo): FontInfo { - let itemId = item.getId(); + const itemId = item.getId(); return this._values[itemId]; } public put(item: BareFontInfo, value: FontInfo): void { - let itemId = item.getId(); + const itemId = item.getId(); this._keys[itemId] = item; this._values[itemId] = value; } public remove(item: BareFontInfo): void { - let itemId = item.getId(); + const itemId = item.getId(); delete this._keys[itemId]; delete this._values[itemId]; } @@ -63,7 +63,7 @@ export function readFontInfo(bareFontInfo: BareFontInfo): FontInfo { } export function restoreFontInfo(storageService: IStorageService): void { - let strStoredFontInfo = storageService.get('editorFontInfo', StorageScope.GLOBAL); + const strStoredFontInfo = storageService.get('editorFontInfo', StorageScope.GLOBAL); if (typeof strStoredFontInfo !== 'string') { return; } @@ -80,7 +80,7 @@ export function restoreFontInfo(storageService: IStorageService): void { } export function saveFontInfo(storageService: IStorageService): void { - let knownFontInfo = CSSBasedConfiguration.INSTANCE.saveFontInfo(); + const knownFontInfo = CSSBasedConfiguration.INSTANCE.saveFontInfo(); if (knownFontInfo.length > 0) { storageService.store('editorFontInfo', JSON.stringify(knownFontInfo), StorageScope.GLOBAL); } @@ -144,10 +144,10 @@ class CSSBasedConfiguration extends Disposable { } private _evictUntrustedReadings(): void { - let values = this._cache.getValues(); + const values = this._cache.getValues(); let somethingRemoved = false; for (let i = 0, len = values.length; i < len; i++) { - let item = values[i]; + const item = values[i]; if (!item.isTrusted) { somethingRemoved = true; this._cache.remove(item); @@ -167,7 +167,7 @@ class CSSBasedConfiguration extends Disposable { // 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++) { - let fontInfo = new FontInfo(savedFontInfo[i], false); + const fontInfo = new FontInfo(savedFontInfo[i], false); this._writeToCache(fontInfo, fontInfo); } } @@ -200,7 +200,7 @@ class CSSBasedConfiguration extends Disposable { } private static createRequest(chr: string, type: CharWidthRequestType, all: CharWidthRequest[], monospace: CharWidthRequest[] | null): CharWidthRequest { - let result = new CharWidthRequest(chr, type); + const result = new CharWidthRequest(chr, type); all.push(result); if (monospace) { monospace.push(result); @@ -209,8 +209,8 @@ class CSSBasedConfiguration extends Disposable { } private static _actualReadConfiguration(bareFontInfo: BareFontInfo): FontInfo { - let all: CharWidthRequest[] = []; - let monospace: CharWidthRequest[] = []; + const all: CharWidthRequest[] = []; + const monospace: CharWidthRequest[] = []; const typicalHalfwidthCharacter = this.createRequest('n', CharWidthRequestType.Regular, all, monospace); const typicalFullwidthCharacter = this.createRequest('\uff4d', CharWidthRequestType.Regular, all, null); @@ -262,7 +262,7 @@ 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 referenceWidth = monospace[0].width; + const referenceWidth = monospace[0].width; for (let i = 1, len = monospace.length; i < len; i++) { const diff = referenceWidth - monospace[i].width; if (diff < -0.001 || diff > 0.001) { diff --git a/src/vs/editor/browser/controller/coreCommands.ts b/src/vs/editor/browser/controller/coreCommands.ts index b6629ad43a7..f1abe319f58 100644 --- a/src/vs/editor/browser/controller/coreCommands.ts +++ b/src/vs/editor/browser/controller/coreCommands.ts @@ -48,7 +48,7 @@ export namespace EditorScroll_ { return false; } - let scrollArg: RawArguments = arg; + const scrollArg: RawArguments = arg; if (!types.isString(scrollArg.to)) { return false; @@ -213,7 +213,7 @@ export namespace RevealLine_ { return false; } - let reveaLineArg: RawArguments = arg; + const reveaLineArg: RawArguments = arg; if (!types.isNumber(reveaLineArg.lineNumber)) { return false; @@ -800,7 +800,7 @@ export namespace CoreNavigationCommands { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); const states = cursors.getAll(); - let newStates: PartialCursorState[] = states.slice(0); + const newStates: PartialCursorState[] = states.slice(0); newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, states[lastAddedCursorIndex], true, args.position, args.viewPosition); cursors.context.model.pushStackElement(); @@ -881,7 +881,7 @@ export namespace CoreNavigationCommands { } private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] { - let result: PartialCursorState[] = []; + const result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; @@ -960,7 +960,7 @@ export namespace CoreNavigationCommands { } private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] { - let result: PartialCursorState[] = []; + const result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; @@ -1280,8 +1280,8 @@ export namespace CoreNavigationCommands { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); const states = cursors.getAll(); - let newStates: PartialCursorState[] = states.slice(0); - let lastAddedState = states[lastAddedCursorIndex]; + const newStates: PartialCursorState[] = states.slice(0); + const lastAddedState = states[lastAddedCursorIndex]; newStates[lastAddedCursorIndex] = CursorMoveCommands.word(context, lastAddedState, lastAddedState.modelState.hasSelection(), args.position); context.model.pushStackElement(); @@ -1338,7 +1338,7 @@ export namespace CoreNavigationCommands { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); const states = cursors.getAll(); - let newStates: PartialCursorState[] = states.slice(0); + const newStates: PartialCursorState[] = states.slice(0); newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, states[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition); cursors.context.model.pushStackElement(); @@ -1685,21 +1685,21 @@ class EditorOrNativeTextInputCommand extends Command { public runCommand(accessor: ServicesAccessor, args: any): void { - let focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor(); + const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor(); // Only if editor text focus (i.e. not if editor has widget focus). if (focusedEditor && focusedEditor.hasTextFocus()) { return this._runEditorHandler(accessor, focusedEditor, args); } // Ignore this action when user is focused on an element that allows for entering text - let activeElement = document.activeElement; + const activeElement = document.activeElement; if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) { document.execCommand(this._inputHandler); return; } // Redirecting to active editor - let activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor(); + const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor(); if (activeEditor) { activeEditor.focus(); return this._runEditorHandler(accessor, activeEditor, args); @@ -1707,7 +1707,7 @@ class EditorOrNativeTextInputCommand extends Command { } private _runEditorHandler(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { - let HANDLER = this._editorHandler; + const HANDLER = this._editorHandler; if (typeof HANDLER === 'string') { editor.trigger('keyboard', HANDLER, args); } else { diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index 1a8af35373f..2c70cab83ac 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -94,7 +94,7 @@ export class MouseHandler extends ViewEventHandler { this.lastMouseLeaveTime = -1; - let mouseEvents = new EditorMouseEventFactory(this.viewHelper.viewDomNode); + const mouseEvents = new EditorMouseEventFactory(this.viewHelper.viewDomNode); this._register(mouseEvents.onContextMenu(this.viewHelper.viewDomNode, (e) => this._onContextMenu(e, true))); @@ -108,14 +108,14 @@ export class MouseHandler extends ViewEventHandler { this._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e))); - let onMouseWheel = (browserEvent: IMouseWheelEvent) => { + const onMouseWheel = (browserEvent: IMouseWheelEvent) => { if (!this._context.configuration.editor.viewInfo.mouseWheelZoom) { return; } - let e = new StandardWheelEvent(browserEvent); + const e = new StandardWheelEvent(browserEvent); if (e.browserEvent!.ctrlKey || e.browserEvent!.metaKey) { - let zoomLevel: number = EditorZoom.getZoomLevel(); - let delta = e.deltaY > 0 ? 1 : -1; + const zoomLevel: number = EditorZoom.getZoomLevel(); + const delta = e.deltaY > 0 ? 1 : -1; EditorZoom.setZoomLevel(zoomLevel + delta); e.preventDefault(); e.stopPropagation(); @@ -148,20 +148,20 @@ export class MouseHandler extends ViewEventHandler { // --- end event handlers public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null { - let clientPos = new ClientCoordinates(clientX, clientY); - let pos = clientPos.toPageCoordinates(); - let editorPos = createEditorPagePosition(this.viewHelper.viewDomNode); + const clientPos = new ClientCoordinates(clientX, clientY); + const pos = clientPos.toPageCoordinates(); + const editorPos = createEditorPagePosition(this.viewHelper.viewDomNode); if (pos.y < editorPos.y || pos.y > editorPos.y + editorPos.height || pos.x < editorPos.x || pos.x > editorPos.x + editorPos.width) { return null; } - let lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData(); + const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData(); return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, editorPos, pos, null); } protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): editorBrowser.IMouseTarget { - let lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData(); + const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData(); return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, e.editorPos, e.pos, testEventTarget ? e.target : null); } @@ -181,7 +181,7 @@ export class MouseHandler extends ViewEventHandler { // In selection/drag operation return; } - let actualMouseMoveTime = e.timestamp; + const actualMouseMoveTime = e.timestamp; if (actualMouseMoveTime < this.lastMouseLeaveTime) { // Due to throttling, this event occurred before the mouse left the editor, therefore ignore it. return; @@ -209,21 +209,21 @@ export class MouseHandler extends ViewEventHandler { } public _onMouseDown(e: EditorMouseEvent): void { - let t = this._createMouseTarget(e, true); + const t = this._createMouseTarget(e, true); - let targetIsContent = (t.type === editorBrowser.MouseTargetType.CONTENT_TEXT || t.type === editorBrowser.MouseTargetType.CONTENT_EMPTY); - let targetIsGutter = (t.type === editorBrowser.MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_DECORATIONS); - let targetIsLineNumbers = (t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS); - let selectOnLineNumbers = this._context.configuration.editor.viewInfo.selectOnLineNumbers; - let targetIsViewZone = (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE); - let targetIsWidget = (t.type === editorBrowser.MouseTargetType.CONTENT_WIDGET); + const targetIsContent = (t.type === editorBrowser.MouseTargetType.CONTENT_TEXT || t.type === editorBrowser.MouseTargetType.CONTENT_EMPTY); + const targetIsGutter = (t.type === editorBrowser.MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_DECORATIONS); + const targetIsLineNumbers = (t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS); + const selectOnLineNumbers = this._context.configuration.editor.viewInfo.selectOnLineNumbers; + const targetIsViewZone = (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE); + const targetIsWidget = (t.type === editorBrowser.MouseTargetType.CONTENT_WIDGET); let shouldHandle = e.leftButton || e.middleButton; if (platform.isMacintosh && e.leftButton && e.ctrlKey) { shouldHandle = false; } - let focus = () => { + const focus = () => { // In IE11, if the focus is in the browser's address bar and // then you click in the editor, calling preventDefault() // will not move focus properly (focus remains the address bar) @@ -243,7 +243,7 @@ export class MouseHandler extends ViewEventHandler { // Do not steal focus e.preventDefault(); } else if (targetIsViewZone) { - let viewZoneData = t.detail; + const viewZoneData = t.detail; if (this.viewHelper.shouldSuppressMouseDownOnViewZone(viewZoneData.viewZoneId)) { focus(); this._mouseDownOperation.start(t.type, e); @@ -312,7 +312,7 @@ class MouseDownOperation extends Disposable { this._lastMouseEvent = e; this._mouseState.setModifiers(e); - let position = this._findMousePosition(e, true); + const position = this._findMousePosition(e, true); if (!position) { // Ignoring because position is unknown return; @@ -334,7 +334,7 @@ class MouseDownOperation extends Disposable { this._mouseState.setStartedOnLineNumbers(targetType === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS); this._mouseState.setStartButtons(e); this._mouseState.setModifiers(e); - let position = this._findMousePosition(e, true); + const position = this._findMousePosition(e, true); if (!position || !position.position) { // Ignoring because position is unknown return; @@ -361,7 +361,7 @@ class MouseDownOperation extends Disposable { createMouseMoveEventMerger(null), (e) => this._onMouseDownThenMove(e), () => { - let position = this._findMousePosition(this._lastMouseEvent!, true); + const position = this._findMousePosition(this._lastMouseEvent!, true); this._viewController.emitMouseDrop({ event: this._lastMouseEvent!, @@ -401,7 +401,7 @@ class MouseDownOperation extends Disposable { if (!this._lastMouseEvent) { return; } - let position = this._findMousePosition(this._lastMouseEvent, false); + const position = this._findMousePosition(this._lastMouseEvent, false); if (!position) { // Ignoring because position is unknown return; @@ -435,7 +435,7 @@ class MouseDownOperation extends Disposable { } } - let aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); + const aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(aboveLineNumber, 1)); } @@ -449,11 +449,11 @@ class MouseDownOperation extends Disposable { } } - let belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); + const belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber))); } - let possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y)); + const possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y)); if (e.posx < editorContent.x) { return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, 1)); @@ -467,13 +467,13 @@ class MouseDownOperation extends Disposable { } private _findMousePosition(e: EditorMouseEvent, testEventTarget: boolean): MouseTarget | null { - let positionOutsideEditor = this._getPositionOutsideEditor(e); + const positionOutsideEditor = this._getPositionOutsideEditor(e); if (positionOutsideEditor) { return positionOutsideEditor; } - let t = this._createMouseTarget(e, testEventTarget); - let hintedPosition = t.position; + const t = this._createMouseTarget(e, testEventTarget); + const hintedPosition = t.position; if (!hintedPosition) { return null; } @@ -490,9 +490,9 @@ class MouseDownOperation extends Disposable { private _helpPositionJumpOverViewZone(viewZoneData: IViewZoneData): Position | null { // Force position on view zones to go above or below depending on where selection started from - let selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn); - let positionBefore = viewZoneData.positionBefore; - let positionAfter = viewZoneData.positionAfter; + const selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn); + const positionBefore = viewZoneData.positionBefore; + const positionAfter = viewZoneData.positionAfter; if (positionBefore && positionAfter) { if (positionBefore.isBefore(selectionStart)) { @@ -594,7 +594,7 @@ class MouseDownState { public trySetCount(setMouseDownCount: number, newMouseDownPosition: Position): void { // a. Invalidate multiple clicking if too much time has passed (will be hit by IE because the detail field of mouse events contains garbage in IE10) - let currentTime = (new Date()).getTime(); + const currentTime = (new Date()).getTime(); if (currentTime - this._lastSetMouseDownCountTime > MouseDownState.CLEAR_MOUSE_DOWN_COUNT_TIME) { setMouseDownCount = 1; } diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 54127e9beb6..70d6b935a2b 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -253,7 +253,7 @@ export class HitTestContext { public static getZoneAtCoord(context: ViewContext, mouseVerticalOffset: number): IViewZoneData | null { // The target is either a view zone or the empty space after the last view-line - let viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset); + const viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset); if (viewZoneWhitespace) { let viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2, @@ -295,16 +295,16 @@ export class HitTestContext { public getFullLineRangeAtCoord(mouseVerticalOffset: number): { range: EditorRange; isAfterLines: boolean; } { if (this._context.viewLayout.isAfterLines(mouseVerticalOffset)) { // Below the last line - let lineNumber = this._context.model.getLineCount(); - let maxLineColumn = this._context.model.getLineMaxColumn(lineNumber); + const lineNumber = this._context.model.getLineCount(); + const maxLineColumn = this._context.model.getLineMaxColumn(lineNumber); return { range: new EditorRange(lineNumber, maxLineColumn, lineNumber, maxLineColumn), isAfterLines: true }; } - let lineNumber = this._context.viewLayout.getLineNumberAtVerticalOffset(mouseVerticalOffset); - let maxLineColumn = this._context.model.getLineMaxColumn(lineNumber); + const lineNumber = this._context.viewLayout.getLineNumberAtVerticalOffset(mouseVerticalOffset); + const maxLineColumn = this._context.model.getLineMaxColumn(lineNumber); return { range: new EditorRange(lineNumber, 1, lineNumber, maxLineColumn), isAfterLines: false @@ -439,8 +439,8 @@ export class MouseTargetFactory { } public mouseTargetIsWidget(e: EditorMouseEvent): boolean { - let t = e.target; - let path = PartFingerprints.collect(t, this._viewHelper.viewDomNode); + const t = e.target; + const path = PartFingerprints.collect(t, this._viewHelper.viewDomNode); // Is it a content widget? if (ElementPath.isChildOfContentWidgets(path) || ElementPath.isChildOfOverflowingContentWidgets(path)) { @@ -459,7 +459,7 @@ export class MouseTargetFactory { const ctx = new HitTestContext(this._context, this._viewHelper, lastViewCursorsRenderData); const request = new HitTestRequest(ctx, editorPos, pos, target); try { - let r = MouseTargetFactory._createMouseTarget(ctx, request, false); + const r = MouseTargetFactory._createMouseTarget(ctx, request, false); // console.log(r.toString()); return r; } catch (err) { @@ -510,7 +510,7 @@ export class MouseTargetFactory { private static _hitTestContentWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null { // Is it a content widget? if (ElementPath.isChildOfContentWidgets(request.targetPath) || ElementPath.isChildOfOverflowingContentWidgets(request.targetPath)) { - let widgetId = ctx.findAttribute(request.target, 'widgetId'); + const widgetId = ctx.findAttribute(request.target, 'widgetId'); if (widgetId) { return request.fulfill(MouseTargetType.CONTENT_WIDGET, null, null, widgetId); } else { @@ -523,7 +523,7 @@ export class MouseTargetFactory { private static _hitTestOverlayWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null { // Is it an overlay widget? if (ElementPath.isChildOfOverlayWidgets(request.targetPath)) { - let widgetId = ctx.findAttribute(request.target, 'widgetId'); + const widgetId = ctx.findAttribute(request.target, 'widgetId'); if (widgetId) { return request.fulfill(MouseTargetType.OVERLAY_WIDGET, null, null, widgetId); } else { @@ -583,9 +583,9 @@ export class MouseTargetFactory { } private static _hitTestViewZone(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null { - let viewZoneData = ctx.getZoneAtCoord(request.mouseVerticalOffset); + const viewZoneData = ctx.getZoneAtCoord(request.mouseVerticalOffset); if (viewZoneData) { - let mouseTargetType = (request.isInContentArea ? MouseTargetType.CONTENT_VIEW_ZONE : MouseTargetType.GUTTER_VIEW_ZONE); + const mouseTargetType = (request.isInContentArea ? MouseTargetType.CONTENT_VIEW_ZONE : MouseTargetType.GUTTER_VIEW_ZONE); return request.fulfill(mouseTargetType, viewZoneData.position, null, viewZoneData); } @@ -602,8 +602,8 @@ export class MouseTargetFactory { private static _hitTestMargin(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null { if (request.isInMarginArea) { - let res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset); - let pos = res.range.getStartPosition(); + const res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset); + const pos = res.range.getStartPosition(); let offset = Math.abs(request.pos.x - request.editorPos.x); const detail: IMarginData = { isAfterLines: res.isAfterLines, @@ -683,7 +683,7 @@ export class MouseTargetFactory { private static _hitTestScrollbarSlider(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null { if (ElementPath.isChildOfScrollableElement(request.targetPath)) { if (request.target && request.target.nodeType === 1) { - let className = request.target.className; + const className = request.target.className; if (className && /\b(slider|scrollbar)\b/.test(className)) { const possibleLineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset); const maxColumn = ctx.model.getLineMaxColumn(possibleLineNumber); @@ -707,8 +707,8 @@ export class MouseTargetFactory { } public getMouseColumn(editorPos: EditorPagePosition, pos: PageCoordinates): number { - let layoutInfo = this._context.configuration.editor.layoutInfo; - let mouseContentHorizontalOffset = this._context.viewLayout.getCurrentScrollLeft() + pos.x - editorPos.x - layoutInfo.contentLeft; + const layoutInfo = this._context.configuration.editor.layoutInfo; + const mouseContentHorizontalOffset = this._context.viewLayout.getCurrentScrollLeft() + pos.x - editorPos.x - layoutInfo.contentLeft; return MouseTargetFactory._getMouseColumn(mouseContentHorizontalOffset, this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth); } @@ -716,14 +716,14 @@ export class MouseTargetFactory { if (mouseContentHorizontalOffset < 0) { return 1; } - let chars = Math.round(mouseContentHorizontalOffset / typicalHalfwidthCharacterWidth); + const chars = Math.round(mouseContentHorizontalOffset / typicalHalfwidthCharacterWidth); return (chars + 1); } private static createMouseTargetFromHitTestPosition(ctx: HitTestContext, request: HitTestRequest, lineNumber: number, column: number): MouseTarget { - let pos = new Position(lineNumber, column); + const pos = new Position(lineNumber, column); - let lineWidth = ctx.getLineWidth(lineNumber); + const lineWidth = ctx.getLineWidth(lineNumber); if (request.mouseContentHorizontalOffset > lineWidth) { if (browser.isEdge && pos.column === 1) { @@ -741,7 +741,7 @@ export class MouseTargetFactory { return request.fulfill(MouseTargetType.UNKNOWN, pos); } - let columnHorizontalOffset = visibleRange.left; + const columnHorizontalOffset = visibleRange.left; if (request.mouseContentHorizontalOffset === columnHorizontalOffset) { return request.fulfill(MouseTargetType.CONTENT_TEXT, pos); @@ -750,7 +750,7 @@ export class MouseTargetFactory { // Let's define a, b, c and check if the offset is in between them... interface OffsetColumn { offset: number; column: number; } - let points: OffsetColumn[] = []; + const points: OffsetColumn[] = []; points.push({ offset: visibleRange.left, column: column }); if (column > 1) { const visibleRange = ctx.visibleRangeForPosition2(lineNumber, column - 1); @@ -786,9 +786,9 @@ export class MouseTargetFactory { // In Chrome, especially on Linux it is possible to click between lines, // so try to adjust the `hity` below so that it lands in the center of a line - let lineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset); - let lineVerticalOffset = ctx.getVerticalOffsetForLineNumber(lineNumber); - let lineCenteredVerticalOffset = lineVerticalOffset + Math.floor(ctx.lineHeight / 2); + const lineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset); + const lineVerticalOffset = ctx.getVerticalOffsetForLineNumber(lineNumber); + const lineCenteredVerticalOffset = lineVerticalOffset + Math.floor(ctx.lineHeight / 2); let adjustedPageY = request.pos.y + (lineCenteredVerticalOffset - request.mouseVerticalOffset); if (adjustedPageY <= request.editorPos.y) { @@ -798,9 +798,9 @@ export class MouseTargetFactory { adjustedPageY = request.editorPos.y + ctx.layoutInfo.height - 1; } - let adjustedPage = new PageCoordinates(request.pos.x, adjustedPageY); + const adjustedPage = new PageCoordinates(request.pos.x, adjustedPageY); - let r = this._actualDoHitTestWithCaretRangeFromPoint(ctx, adjustedPage.toClientCoordinates()); + const r = this._actualDoHitTestWithCaretRangeFromPoint(ctx, adjustedPage.toClientCoordinates()); if (r.position) { return r; } @@ -811,7 +811,7 @@ export class MouseTargetFactory { private static _actualDoHitTestWithCaretRangeFromPoint(ctx: HitTestContext, coords: ClientCoordinates): IHitTestResult { - let range: Range = document.caretRangeFromPoint(coords.clientX, coords.clientY); + const range: Range = document.caretRangeFromPoint(coords.clientX, coords.clientY); if (!range || !range.startContainer) { return { @@ -821,18 +821,18 @@ export class MouseTargetFactory { } // Chrome always hits a TEXT_NODE, while Edge sometimes hits a token span - let startContainer = range.startContainer; + const startContainer = range.startContainer; let hitTarget: HTMLElement | null = null; if (startContainer.nodeType === startContainer.TEXT_NODE) { // startContainer is expected to be the token text - let parent1 = startContainer.parentNode; // expected to be the token span - let parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span - let parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div - let parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null; + const parent1 = startContainer.parentNode; // expected to be the token span + const parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span + const parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div + const parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null; if (parent3ClassName === ViewLine.CLASS_NAME) { - let p = ctx.getPositionFromDOMInfo(parent1, range.startOffset); + const p = ctx.getPositionFromDOMInfo(parent1, range.startOffset); return { position: p, hitTarget: null @@ -842,12 +842,12 @@ export class MouseTargetFactory { } } else if (startContainer.nodeType === startContainer.ELEMENT_NODE) { // startContainer is expected to be the token span - let parent1 = startContainer.parentNode; // expected to be the view line container span - let parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line div - let parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : null; + const parent1 = startContainer.parentNode; // expected to be the view line container span + const parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line div + const parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : null; if (parent2ClassName === ViewLine.CLASS_NAME) { - let p = ctx.getPositionFromDOMInfo(startContainer, (startContainer).textContent!.length); + const p = ctx.getPositionFromDOMInfo(startContainer, (startContainer).textContent!.length); return { position: p, hitTarget: null @@ -867,17 +867,17 @@ export class MouseTargetFactory { * Most probably Gecko */ private static _doHitTestWithCaretPositionFromPoint(ctx: HitTestContext, coords: ClientCoordinates): IHitTestResult { - let hitResult: { offsetNode: Node; offset: number; } = (document).caretPositionFromPoint(coords.clientX, coords.clientY); + const hitResult: { offsetNode: Node; offset: number; } = (document).caretPositionFromPoint(coords.clientX, coords.clientY); if (hitResult.offsetNode.nodeType === hitResult.offsetNode.TEXT_NODE) { // offsetNode is expected to be the token text - let parent1 = hitResult.offsetNode.parentNode; // expected to be the token span - let parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span - let parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div - let parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null; + const parent1 = hitResult.offsetNode.parentNode; // expected to be the token span + const parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span + const parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div + const parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null; if (parent3ClassName === ViewLine.CLASS_NAME) { - let p = ctx.getPositionFromDOMInfo(hitResult.offsetNode.parentNode, hitResult.offset); + const p = ctx.getPositionFromDOMInfo(hitResult.offsetNode.parentNode, hitResult.offset); return { position: p, hitTarget: null @@ -903,7 +903,7 @@ export class MouseTargetFactory { let resultPosition: Position | null = null; let resultHitTarget: Element | null = null; - let textRange: IETextRange = (document.body).createTextRange(); + const textRange: IETextRange = (document.body).createTextRange(); try { textRange.moveToPoint(coords.clientX, coords.clientY); } catch (err) { @@ -916,14 +916,14 @@ export class MouseTargetFactory { textRange.collapse(true); // Now, let's do our best to figure out what we hit :) - let parentElement = textRange ? textRange.parentElement() : null; - let parent1 = parentElement ? parentElement.parentNode : null; - let parent2 = parent1 ? parent1.parentNode : null; + const parentElement = textRange ? textRange.parentElement() : null; + const parent1 = parentElement ? parentElement.parentNode : null; + const parent2 = parent1 ? parent1.parentNode : null; - let parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : ''; + const parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : ''; if (parent2ClassName === ViewLine.CLASS_NAME) { - let rangeToContainEntireSpan = textRange.duplicate(); + const rangeToContainEntireSpan = textRange.duplicate(); rangeToContainEntireSpan.moveToElementText(parentElement!); rangeToContainEntireSpan.setEndPoint('EndToStart', textRange); diff --git a/src/vs/editor/browser/controller/pointerHandler.ts b/src/vs/editor/browser/controller/pointerHandler.ts index c97ebab90ad..57cd5cc879d 100644 --- a/src/vs/editor/browser/controller/pointerHandler.ts +++ b/src/vs/editor/browser/controller/pointerHandler.ts @@ -18,7 +18,7 @@ interface IThrottledGestureEvent { } function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent, currentEvent: MSGestureEvent): IThrottledGestureEvent { - let r = { + const r = { translationY: currentEvent.translationY, translationX: currentEvent.translationX }; @@ -48,13 +48,13 @@ class MsPointerHandler extends MouseHandler implements IDisposable { this._installGestureHandlerTimeout = window.setTimeout(() => { this._installGestureHandlerTimeout = -1; if ((window).MSGesture) { - let touchGesture = new MSGesture(); - let penGesture = new MSGesture(); + const touchGesture = new MSGesture(); + const penGesture = new MSGesture(); touchGesture.target = this.viewHelper.linesContentDomNode; penGesture.target = this.viewHelper.linesContentDomNode; this.viewHelper.linesContentDomNode.addEventListener('MSPointerDown', (e: MSPointerEvent) => { // Circumvent IE11 breaking change in e.pointerType & TypeScript's stale definitions - let pointerType = e.pointerType; + const pointerType = e.pointerType; if (pointerType === ((e).MSPOINTER_TYPE_MOUSE || 'mouse')) { this._lastPointerType = 'mouse'; return; @@ -80,8 +80,8 @@ class MsPointerHandler extends MouseHandler implements IDisposable { } private _onCaptureGestureTap(rawEvent: MSGestureEvent): void { - let e = new EditorMouseEvent(rawEvent, this.viewHelper.viewDomNode); - let t = this._createMouseTarget(e, false); + const e = new EditorMouseEvent(rawEvent, this.viewHelper.viewDomNode); + const t = this._createMouseTarget(e, false); if (t.position) { this.viewController.moveTo(t.position); } @@ -127,12 +127,12 @@ class StandardPointerHandler extends MouseHandler implements IDisposable { // TODO@Alex: replace the usage of MSGesture here with something that works across all browsers if ((window).MSGesture) { - let touchGesture = new MSGesture(); - let penGesture = new MSGesture(); + const touchGesture = new MSGesture(); + const penGesture = new MSGesture(); touchGesture.target = this.viewHelper.linesContentDomNode; penGesture.target = this.viewHelper.linesContentDomNode; this.viewHelper.linesContentDomNode.addEventListener('pointerdown', (e: MSPointerEvent) => { - let pointerType = e.pointerType; + const pointerType = e.pointerType; if (pointerType === 'mouse') { this._lastPointerType = 'mouse'; return; @@ -158,8 +158,8 @@ class StandardPointerHandler extends MouseHandler implements IDisposable { } private _onCaptureGestureTap(rawEvent: MSGestureEvent): void { - let e = new EditorMouseEvent(rawEvent, this.viewHelper.viewDomNode); - let t = this._createMouseTarget(e, false); + const e = new EditorMouseEvent(rawEvent, this.viewHelper.viewDomNode); + const t = this._createMouseTarget(e, false); if (t.position) { this.viewController.moveTo(t.position); } @@ -207,7 +207,7 @@ class TouchHandler extends MouseHandler { this.viewHelper.focusTextArea(); - let target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false); + const target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false); if (target.position) { this.viewController.moveTo(target.position); diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts index 697ce880544..b907a3bfa6a 100644 --- a/src/vs/editor/browser/controller/textAreaState.ts +++ b/src/vs/editor/browser/controller/textAreaState.ts @@ -233,26 +233,26 @@ export class PagedScreenReaderStrategy { } private static _getRangeForPage(page: number): Range { - let offset = page * PagedScreenReaderStrategy._LINES_PER_PAGE; - let startLineNumber = offset + 1; - let endLineNumber = offset + PagedScreenReaderStrategy._LINES_PER_PAGE; + const offset = page * PagedScreenReaderStrategy._LINES_PER_PAGE; + const startLineNumber = offset + 1; + const endLineNumber = offset + PagedScreenReaderStrategy._LINES_PER_PAGE; return new Range(startLineNumber, 1, endLineNumber + 1, 1); } public static fromEditorSelection(previousState: TextAreaState, model: ISimpleModel, selection: Range, trimLongText: boolean): TextAreaState { - let selectionStartPage = PagedScreenReaderStrategy._getPageOfLine(selection.startLineNumber); - let selectionStartPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionStartPage); + const selectionStartPage = PagedScreenReaderStrategy._getPageOfLine(selection.startLineNumber); + const selectionStartPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionStartPage); - let selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber); - let selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage); + const selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber); + const selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage); - let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!; + const pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!; let pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF); - let lastLine = model.getLineCount(); - let lastLineMaxColumn = model.getLineMaxColumn(lastLine); - let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!; + const lastLine = model.getLineCount(); + const lastLineMaxColumn = model.getLineMaxColumn(lastLine); + const posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!; let posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF); @@ -261,8 +261,8 @@ export class PagedScreenReaderStrategy { // take full selection text = model.getValueInRange(selection, EndOfLinePreference.LF); } else { - let selectionRange1 = selectionStartPageRange.intersectRanges(selection)!; - let selectionRange2 = selectionEndPageRange.intersectRanges(selection)!; + const selectionRange1 = selectionStartPageRange.intersectRanges(selection)!; + const selectionRange2 = selectionEndPageRange.intersectRanges(selection)!; text = ( model.getValueInRange(selectionRange1, EndOfLinePreference.LF) + String.fromCharCode(8230) diff --git a/src/vs/editor/browser/core/editorState.ts b/src/vs/editor/browser/core/editorState.ts index f1351bec8db..9206df4dcf9 100644 --- a/src/vs/editor/browser/core/editorState.ts +++ b/src/vs/editor/browser/core/editorState.ts @@ -29,7 +29,7 @@ export class EditorState { this.flags = flags; if ((this.flags & CodeEditorStateFlag.Value) !== 0) { - let model = editor.getModel(); + const model = editor.getModel(); this.modelVersionId = model ? strings.format('{0}#{1}', model.uri.toString(), model.getVersionId()) : null; } if ((this.flags & CodeEditorStateFlag.Position) !== 0) { @@ -49,7 +49,7 @@ export class EditorState { if (!(other instanceof EditorState)) { return false; } - let state = other; + const state = other; if (this.modelVersionId !== state.modelVersionId) { return false; diff --git a/src/vs/editor/browser/editorDom.ts b/src/vs/editor/browser/editorDom.ts index 4168c714fbb..23a905a4aeb 100644 --- a/src/vs/editor/browser/editorDom.ts +++ b/src/vs/editor/browser/editorDom.ts @@ -59,7 +59,7 @@ export class EditorPagePosition { } export function createEditorPagePosition(editorViewDomNode: HTMLElement): EditorPagePosition { - let editorPos = dom.getDomNodePagePosition(editorViewDomNode); + const editorPos = dom.getDomNodePagePosition(editorViewDomNode); return new EditorPagePosition(editorPos.left, editorPos.top, editorPos.width, editorPos.height); } @@ -124,7 +124,7 @@ export class EditorMouseEventFactory { } public onMouseMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable { - let myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => { + const myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => { return merger(lastEvent, this._create(currentEvent)); }; return dom.addDisposableThrottledListener(target, 'mousemove', callback, myMerger, minimumTimeMs); @@ -157,7 +157,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable { this._globalMouseMoveMonitor.stopMonitoring(true); }, true); - let myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => { + const myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => { return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode)); }; diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index b7061803c01..742095a1ad1 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -136,7 +136,7 @@ export abstract class EditorCommand extends Command { } public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { - let controller = controllerGetter(editor); + const controller = controllerGetter(editor); if (controller) { this._callback(controllerGetter(editor), args); } @@ -148,7 +148,7 @@ export abstract class EditorCommand extends Command { const codeEditorService = accessor.get(ICodeEditorService); // Find the editor with text focus or active - let editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); + const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); if (!editor) { // well, at least we tried... return; @@ -267,7 +267,7 @@ export function registerDefaultLanguageCommand(id: string, handler: (model: ITex return accessor.get(ITextModelService).createModelReference(resource).then(reference => { return new Promise((resolve, reject) => { try { - let result = handler(reference.object.textEditorModel, Position.lift(position), args); + const result = handler(reference.object.textEditorModel, Position.lift(position), args); resolve(result); } catch (err) { reject(err); diff --git a/src/vs/editor/browser/services/abstractCodeEditorService.ts b/src/vs/editor/browser/services/abstractCodeEditorService.ts index 55b6a6dcec1..f6a20ee4e11 100644 --- a/src/vs/editor/browser/services/abstractCodeEditorService.ts +++ b/src/vs/editor/browser/services/abstractCodeEditorService.ts @@ -73,7 +73,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC getFocusedCodeEditor(): ICodeEditor | null { let editorWithWidgetFocus: ICodeEditor | null = null; - let editors = this.listCodeEditors(); + const editors = this.listCodeEditors(); for (const editor of editors) { if (editor.hasTextFocus()) { diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index 36dd7415722..f99a7f87b2e 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -30,7 +30,7 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void { let provider = this._decorationOptionProviders[key]; if (!provider) { - let providerArgs: ProviderArguments = { + const providerArgs: ProviderArguments = { styleSheet: this._styleSheet, key: key, parentTypeKey: parentTypeKey, @@ -47,7 +47,7 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { } public removeDecorationType(key: string): void { - let provider = this._decorationOptionProviders[key]; + const provider = this._decorationOptionProviders[key]; if (provider) { provider.refCount--; if (provider.refCount <= 0) { @@ -59,7 +59,7 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { } public resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions { - let provider = this._decorationOptionProviders[decorationTypeKey]; + const provider = this._decorationOptionProviders[decorationTypeKey]; if (!provider) { throw new Error('Unknown decoration type key: ' + decorationTypeKey); } @@ -92,7 +92,7 @@ class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvide } public getOptions(codeEditorService: AbstractCodeEditorService, writable: boolean): IModelDecorationOptions { - let options = codeEditorService.resolveDecorationOptions(this._parentTypeKey, true); + const options = codeEditorService.resolveDecorationOptions(this._parentTypeKey, true); if (this._beforeContentRules) { options.beforeContentClassName = this._beforeContentRules.className; } @@ -168,12 +168,12 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { this.afterContentClassName = createCSSRules(ModelDecorationCSSRuleType.AfterContentClassName); this.glyphMarginClassName = createCSSRules(ModelDecorationCSSRuleType.GlyphMarginClassName); - let options = providerArgs.options; + const options = providerArgs.options; this.isWholeLine = Boolean(options.isWholeLine); this.stickiness = options.rangeBehavior; - let lightOverviewRulerColor = options.light && options.light.overviewRulerColor || options.overviewRulerColor; - let darkOverviewRulerColor = options.dark && options.dark.overviewRulerColor || options.overviewRulerColor; + const lightOverviewRulerColor = options.light && options.light.overviewRulerColor || options.overviewRulerColor; + const darkOverviewRulerColor = options.dark && options.dark.overviewRulerColor || options.overviewRulerColor; if ( typeof lightOverviewRulerColor !== 'undefined' || typeof darkOverviewRulerColor !== 'undefined' @@ -307,7 +307,7 @@ class DecorationCSSRules { } private _buildCSS(): void { - let options = this._providerArgs.options; + const options = this._providerArgs.options; let unthemedCSS: string, lightCSS: string, darkCSS: string; switch (this._ruleType) { case ModelDecorationCSSRuleType.ClassName: @@ -338,7 +338,7 @@ class DecorationCSSRules { default: throw new Error('Unknown rule type: ' + this._ruleType); } - let sheet = this._providerArgs.styleSheet.sheet; + const sheet = this._providerArgs.styleSheet.sheet; let hasContent = false; if (unthemedCSS.length > 0) { @@ -367,7 +367,7 @@ class DecorationCSSRules { if (!opts) { return ''; } - let cssTextArr: string[] = []; + const cssTextArr: string[] = []; this.collectCSSText(opts, ['backgroundColor'], cssTextArr); this.collectCSSText(opts, ['outline', 'outlineColor', 'outlineStyle', 'outlineWidth'], cssTextArr); this.collectBorderSettingsCSSText(opts, cssTextArr); @@ -381,7 +381,7 @@ class DecorationCSSRules { if (!opts) { return ''; } - let cssTextArr: string[] = []; + const cssTextArr: string[] = []; this.collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'cursor', 'color', 'opacity', 'letterSpacing'], cssTextArr); if (opts.letterSpacing) { this._hasLetterSpacing = true; @@ -396,7 +396,7 @@ class DecorationCSSRules { if (!opts) { return ''; } - let cssTextArr: string[] = []; + const cssTextArr: string[] = []; if (typeof opts !== 'undefined') { this.collectBorderSettingsCSSText(opts, cssTextArr); @@ -425,7 +425,7 @@ class DecorationCSSRules { if (!opts) { return ''; } - let cssTextArr: string[] = []; + const cssTextArr: string[] = []; if (typeof opts.gutterIconPath !== 'undefined') { cssTextArr.push(strings.format(_CSS_MAP.gutterIconPath, URI.revive(opts.gutterIconPath).toString(true).replace(/'/g, '%27'))); @@ -446,9 +446,9 @@ class DecorationCSSRules { } private collectCSSText(opts: any, properties: string[], cssTextArr: string[]): boolean { - let lenBefore = cssTextArr.length; + const lenBefore = cssTextArr.length; for (let property of properties) { - let value = this.resolveValue(opts[property]); + const value = this.resolveValue(opts[property]); if (typeof value === 'string') { cssTextArr.push(strings.format(_CSS_MAP[property], value)); } @@ -459,7 +459,7 @@ class DecorationCSSRules { private resolveValue(value: string | ThemeColor): string { if (isThemeColor(value)) { this._usesThemeColors = true; - let color = this._theme.getColor(value.id); + const color = this._theme.getColor(value.id); if (color) { return color.toString(); } diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index bb087386420..7c7db40a3cf 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -98,7 +98,7 @@ export class ViewController { } private _validateViewColumn(viewPosition: Position): Position { - let minColumn = this.viewModel.getLineMinColumn(viewPosition.lineNumber); + const minColumn = this.viewModel.getLineMinColumn(viewPosition.lineNumber); if (viewPosition.column < minColumn) { return new Position(viewPosition.lineNumber, minColumn); } diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index f3b304c9142..256fa4f67c1 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -105,7 +105,7 @@ export class View extends ViewEventHandler { this._renderAnimationFrame = null; this.outgoingEvents = outgoingEvents; - let viewController = new ViewController(configuration, model, this.outgoingEvents, commandDelegate); + const viewController = new ViewController(configuration, model, this.outgoingEvents, commandDelegate); // The event dispatcher will always go through _renderOnce before dispatching any events this.eventDispatcher = new ViewEventDispatcher((callback: () => void) => this._renderOnce(callback)); @@ -167,21 +167,21 @@ export class View extends ViewEventHandler { this.viewParts.push(this.viewZones); // Decorations overview ruler - let decorationsOverviewRuler = new DecorationsOverviewRuler(this._context); + const decorationsOverviewRuler = new DecorationsOverviewRuler(this._context); this.viewParts.push(decorationsOverviewRuler); - let scrollDecoration = new ScrollDecorationViewPart(this._context); + const scrollDecoration = new ScrollDecorationViewPart(this._context); this.viewParts.push(scrollDecoration); - let contentViewOverlays = new ContentViewOverlays(this._context); + const contentViewOverlays = new ContentViewOverlays(this._context); this.viewParts.push(contentViewOverlays); contentViewOverlays.addDynamicOverlay(new CurrentLineHighlightOverlay(this._context)); contentViewOverlays.addDynamicOverlay(new SelectionsOverlay(this._context)); contentViewOverlays.addDynamicOverlay(new IndentGuidesOverlay(this._context)); contentViewOverlays.addDynamicOverlay(new DecorationsOverlay(this._context)); - let marginViewOverlays = new MarginViewOverlays(this._context); + const marginViewOverlays = new MarginViewOverlays(this._context); this.viewParts.push(marginViewOverlays); marginViewOverlays.addDynamicOverlay(new CurrentLineMarginHighlightOverlay(this._context)); marginViewOverlays.addDynamicOverlay(new GlyphMarginOverlay(this._context)); @@ -189,7 +189,7 @@ export class View extends ViewEventHandler { marginViewOverlays.addDynamicOverlay(new LinesDecorationsOverlay(this._context)); marginViewOverlays.addDynamicOverlay(new LineNumbersOverlay(this._context)); - let margin = new Margin(this._context); + const margin = new Margin(this._context); margin.getDomNode().appendChild(this.viewZones.marginDomNode); margin.getDomNode().appendChild(marginViewOverlays.getDomNode()); this.viewParts.push(margin); @@ -205,16 +205,16 @@ export class View extends ViewEventHandler { this.overlayWidgets = new ViewOverlayWidgets(this._context); this.viewParts.push(this.overlayWidgets); - let rulers = new Rulers(this._context); + const rulers = new Rulers(this._context); this.viewParts.push(rulers); - let minimap = new Minimap(this._context); + const minimap = new Minimap(this._context); this.viewParts.push(minimap); // -------------- Wire dom nodes up if (decorationsOverviewRuler) { - let overviewRulerData = this._scrollbar.getOverviewRulerLayoutInfo(); + const overviewRulerData = this._scrollbar.getOverviewRulerLayoutInfo(); overviewRulerData.parent.insertBefore(decorationsOverviewRuler.getDomNode(), overviewRulerData.insertBefore); } @@ -297,7 +297,7 @@ export class View extends ViewEventHandler { } private getEditorClassName() { - let focused = this._textAreaHandler.isFocused() ? ' focused' : ''; + const focused = this._textAreaHandler.isFocused() ? ' focused' : ''; return this._context.configuration.editor.editorClassName + ' ' + getThemeTypeSelector(this._context.theme.type) + focused; } @@ -356,7 +356,7 @@ export class View extends ViewEventHandler { } private _renderOnce(callback: () => any): any { - let r = safeInvokeNoArg(callback); + const r = safeInvokeNoArg(callback); this._scheduleRender(); return r; } @@ -379,7 +379,7 @@ export class View extends ViewEventHandler { private _getViewPartsToRender(): ViewPart[] { let result: ViewPart[] = [], resultLen = 0; for (let i = 0, len = this.viewParts.length; i < len; i++) { - let viewPart = this.viewParts[i]; + const viewPart = this.viewParts[i]; if (viewPart.shouldRender()) { result[resultLen++] = viewPart; } @@ -402,7 +402,7 @@ export class View extends ViewEventHandler { const partialViewportData = this._context.viewLayout.getLinesViewportData(); this._context.model.setViewport(partialViewportData.startLineNumber, partialViewportData.endLineNumber, partialViewportData.centeredLineNumber); - let viewportData = new ViewportData( + const viewportData = new ViewportData( this._cursor.getViewSelections(), partialViewportData, this._context.viewLayout.getWhitespaceViewportData(), @@ -422,16 +422,16 @@ export class View extends ViewEventHandler { viewPartsToRender = this._getViewPartsToRender(); } - let renderingContext = new RenderingContext(this._context.viewLayout, viewportData, this.viewLines); + const renderingContext = new RenderingContext(this._context.viewLayout, viewportData, this.viewLines); // Render the rest of the parts for (let i = 0, len = viewPartsToRender.length; i < len; i++) { - let viewPart = viewPartsToRender[i]; + const viewPart = viewPartsToRender[i]; viewPart.prepareRender(renderingContext); } for (let i = 0, len = viewPartsToRender.length; i < len; i++) { - let viewPart = viewPartsToRender[i]; + const viewPart = viewPartsToRender[i]; viewPart.render(renderingContext); viewPart.onDidRender(); } @@ -452,11 +452,11 @@ export class View extends ViewEventHandler { } public getOffsetForColumn(modelLineNumber: number, modelColumn: number): number { - let modelPosition = this._context.model.validateModelPosition({ + const modelPosition = this._context.model.validateModelPosition({ lineNumber: modelLineNumber, column: modelColumn }); - let viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(modelPosition); + const viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(modelPosition); this._flushAccumulatedAndRenderNow(); const visibleRange = this.viewLines.visibleRangeForPosition(new Position(viewPosition.lineNumber, viewPosition.column)); if (!visibleRange) { @@ -477,7 +477,7 @@ export class View extends ViewEventHandler { let zonesHaveChanged = false; this._renderOnce(() => { - let changeAccessor: editorBrowser.IViewZoneChangeAccessor = { + const changeAccessor: editorBrowser.IViewZoneChangeAccessor = { addZone: (zone: editorBrowser.IViewZone): number => { zonesHaveChanged = true; return this.viewZones.addZone(zone); @@ -516,7 +516,7 @@ export class View extends ViewEventHandler { // Force everything to render... this.viewLines.forceShouldRender(); for (let i = 0, len = this.viewParts.length; i < len; i++) { - let viewPart = this.viewParts[i]; + const viewPart = this.viewParts[i]; viewPart.forceShouldRender(); } } @@ -542,9 +542,9 @@ export class View extends ViewEventHandler { } public layoutContentWidget(widgetData: IContentWidgetData): void { - let newPosition = widgetData.position ? widgetData.position.position : null; - let newRange = widgetData.position ? widgetData.position.range : null; - let newPreference = widgetData.position ? widgetData.position.preference : null; + const newPosition = widgetData.position ? widgetData.position.position : null; + const newRange = widgetData.position ? widgetData.position.range : null; + const newPreference = widgetData.position ? widgetData.position.preference : null; this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newRange, newPreference); this._scheduleRender(); } @@ -561,8 +561,8 @@ export class View extends ViewEventHandler { } public layoutOverlayWidget(widgetData: IOverlayWidgetData): void { - let newPreference = widgetData.position ? widgetData.position.preference : null; - let shouldRender = this.overlayWidgets.setWidgetPosition(widgetData.widget, newPreference); + const newPreference = widgetData.position ? widgetData.position.preference : null; + const shouldRender = this.overlayWidgets.setWidgetPosition(widgetData.widget, newPreference); if (shouldRender) { this._scheduleRender(); } diff --git a/src/vs/editor/browser/view/viewLayer.ts b/src/vs/editor/browser/view/viewLayer.ts index aede693ffdb..b16f615c3b1 100644 --- a/src/vs/editor/browser/view/viewLayer.ts +++ b/src/vs/editor/browser/view/viewLayer.ts @@ -77,7 +77,7 @@ export class RenderedLinesCollection { } public getLine(lineNumber: number): T { - let lineIndex = lineNumber - this._rendLineNumberStart; + const lineIndex = lineNumber - this._rendLineNumberStart; if (lineIndex < 0 || lineIndex >= this._lines.length) { throw new Error('Illegal value for lineNumber'); } @@ -93,12 +93,12 @@ export class RenderedLinesCollection { return null; } - let startLineNumber = this.getStartLineNumber(); - let endLineNumber = this.getEndLineNumber(); + const startLineNumber = this.getStartLineNumber(); + const endLineNumber = this.getEndLineNumber(); if (deleteToLineNumber < startLineNumber) { // deleting above the viewport - let deleteCnt = deleteToLineNumber - deleteFromLineNumber + 1; + const deleteCnt = deleteToLineNumber - deleteFromLineNumber + 1; this._rendLineNumberStart -= deleteCnt; return null; } @@ -112,7 +112,7 @@ export class RenderedLinesCollection { let deleteStartIndex = 0; let deleteCount = 0; for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) { - let lineIndex = lineNumber - this._rendLineNumberStart; + const lineIndex = lineNumber - this._rendLineNumberStart; if (deleteFromLineNumber <= lineNumber && lineNumber <= deleteToLineNumber) { // this is a line to be deleted @@ -141,7 +141,7 @@ export class RenderedLinesCollection { this._rendLineNumberStart -= deleteAboveCount; } - let deleted = this._lines.splice(deleteStartIndex, deleteCount); + const deleted = this._lines.splice(deleteStartIndex, deleteCount); return deleted; } @@ -151,8 +151,8 @@ export class RenderedLinesCollection { return false; } - let startLineNumber = this.getStartLineNumber(); - let endLineNumber = this.getEndLineNumber(); + const startLineNumber = this.getStartLineNumber(); + const endLineNumber = this.getEndLineNumber(); let someoneNotified = false; @@ -173,9 +173,9 @@ export class RenderedLinesCollection { return null; } - let insertCnt = insertToLineNumber - insertFromLineNumber + 1; - let startLineNumber = this.getStartLineNumber(); - let endLineNumber = this.getEndLineNumber(); + const insertCnt = insertToLineNumber - insertFromLineNumber + 1; + const startLineNumber = this.getStartLineNumber(); + const endLineNumber = this.getEndLineNumber(); if (insertFromLineNumber <= startLineNumber) { // inserting above the viewport @@ -190,19 +190,19 @@ export class RenderedLinesCollection { if (insertCnt + insertFromLineNumber > endLineNumber) { // insert inside the viewport in such a way that all remaining lines are pushed outside - let deleted = this._lines.splice(insertFromLineNumber - this._rendLineNumberStart, endLineNumber - insertFromLineNumber + 1); + const deleted = this._lines.splice(insertFromLineNumber - this._rendLineNumberStart, endLineNumber - insertFromLineNumber + 1); return deleted; } // insert inside the viewport, push out some lines, but not all remaining lines - let newLines: T[] = []; + const newLines: T[] = []; for (let i = 0; i < insertCnt; i++) { newLines[i] = this._createLine(); } - let insertIndex = insertFromLineNumber - this._rendLineNumberStart; - let beforeLines = this._lines.slice(0, insertIndex); - let afterLines = this._lines.slice(insertIndex, this._lines.length - insertCnt); - let deletedLines = this._lines.slice(this._lines.length - insertCnt, this._lines.length); + const insertIndex = insertFromLineNumber - this._rendLineNumberStart; + const beforeLines = this._lines.slice(0, insertIndex); + const afterLines = this._lines.slice(insertIndex, this._lines.length - insertCnt); + const deletedLines = this._lines.slice(this._lines.length - insertCnt, this._lines.length); this._lines = beforeLines.concat(newLines).concat(afterLines); @@ -215,23 +215,23 @@ export class RenderedLinesCollection { return false; } - let startLineNumber = this.getStartLineNumber(); - let endLineNumber = this.getEndLineNumber(); + const startLineNumber = this.getStartLineNumber(); + const endLineNumber = this.getEndLineNumber(); let notifiedSomeone = false; for (let i = 0, len = ranges.length; i < len; i++) { - let rng = ranges[i]; + const rng = ranges[i]; if (rng.toLineNumber < startLineNumber || rng.fromLineNumber > endLineNumber) { // range outside viewport continue; } - let from = Math.max(startLineNumber, rng.fromLineNumber); - let to = Math.min(endLineNumber, rng.toLineNumber); + const from = Math.max(startLineNumber, rng.fromLineNumber); + const to = Math.min(endLineNumber, rng.toLineNumber); for (let lineNumber = from; lineNumber <= to; lineNumber++) { - let lineIndex = lineNumber - this._rendLineNumberStart; + const lineIndex = lineNumber - this._rendLineNumberStart; this._lines[lineIndex].onTokensChanged(); notifiedSomeone = true; } @@ -258,7 +258,7 @@ export class VisibleLinesCollection { } private _createDomNode(): FastDomNode { - let domNode = createFastDomNode(document.createElement('div')); + const domNode = createFastDomNode(document.createElement('div')); domNode.setClassName('view-layer'); domNode.setPosition('absolute'); domNode.domNode.setAttribute('role', 'presentation'); @@ -283,11 +283,11 @@ export class VisibleLinesCollection { } public onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean { - let deleted = this._linesCollection.onLinesDeleted(e.fromLineNumber, e.toLineNumber); + const deleted = this._linesCollection.onLinesDeleted(e.fromLineNumber, e.toLineNumber); if (deleted) { // Remove from DOM for (let i = 0, len = deleted.length; i < len; i++) { - let lineDomNode = deleted[i].getDomNode(); + const lineDomNode = deleted[i].getDomNode(); if (lineDomNode) { this.domNode.domNode.removeChild(lineDomNode); } @@ -298,11 +298,11 @@ export class VisibleLinesCollection { } public onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean { - let deleted = this._linesCollection.onLinesInserted(e.fromLineNumber, e.toLineNumber); + const deleted = this._linesCollection.onLinesInserted(e.fromLineNumber, e.toLineNumber); if (deleted) { // Remove from DOM for (let i = 0, len = deleted.length; i < len; i++) { - let lineDomNode = deleted[i].getDomNode(); + const lineDomNode = deleted[i].getDomNode(); if (lineDomNode) { this.domNode.domNode.removeChild(lineDomNode); } @@ -340,18 +340,18 @@ export class VisibleLinesCollection { public renderLines(viewportData: ViewportData): void { - let inp = this._linesCollection._get(); + const inp = this._linesCollection._get(); - let renderer = new ViewLayerRenderer(this.domNode.domNode, this._host, viewportData); + const renderer = new ViewLayerRenderer(this.domNode.domNode, this._host, viewportData); - let ctx: IRendererContext = { + const ctx: IRendererContext = { rendLineNumberStart: inp.rendLineNumberStart, lines: inp.lines, linesLength: inp.lines.length }; // Decide if this render will do a single update (single large .innerHTML) or many updates (inserting/removing dom nodes) - let resCtx = renderer.render(ctx, viewportData.startLineNumber, viewportData.endLineNumber, viewportData.relativeVerticalOffset); + const resCtx = renderer.render(ctx, viewportData.startLineNumber, viewportData.endLineNumber, viewportData.relativeVerticalOffset); this._linesCollection._set(resCtx.rendLineNumberStart, resCtx.lines); } @@ -377,7 +377,7 @@ class ViewLayerRenderer { public render(inContext: IRendererContext, startLineNumber: number, stopLineNumber: number, deltaTop: number[]): IRendererContext { - let ctx: IRendererContext = { + const ctx: IRendererContext = { rendLineNumberStart: inContext.rendLineNumberStart, lines: inContext.lines.slice(0), linesLength: inContext.linesLength @@ -406,15 +406,15 @@ class ViewLayerRenderer { if (ctx.rendLineNumberStart > startLineNumber) { // Insert lines before - let fromLineNumber = startLineNumber; - let toLineNumber = Math.min(stopLineNumber, ctx.rendLineNumberStart - 1); + const fromLineNumber = startLineNumber; + const toLineNumber = Math.min(stopLineNumber, ctx.rendLineNumberStart - 1); if (fromLineNumber <= toLineNumber) { this._insertLinesBefore(ctx, fromLineNumber, toLineNumber, deltaTop, startLineNumber); ctx.linesLength += toLineNumber - fromLineNumber + 1; } } else if (ctx.rendLineNumberStart < startLineNumber) { // Remove lines before - let removeCnt = Math.min(ctx.linesLength, startLineNumber - ctx.rendLineNumberStart); + const removeCnt = Math.min(ctx.linesLength, startLineNumber - ctx.rendLineNumberStart); if (removeCnt > 0) { this._removeLinesBefore(ctx, removeCnt); ctx.linesLength -= removeCnt; @@ -425,8 +425,8 @@ class ViewLayerRenderer { if (ctx.rendLineNumberStart + ctx.linesLength - 1 < stopLineNumber) { // Insert lines after - let fromLineNumber = ctx.rendLineNumberStart + ctx.linesLength; - let toLineNumber = stopLineNumber; + const fromLineNumber = ctx.rendLineNumberStart + ctx.linesLength; + const toLineNumber = stopLineNumber; if (fromLineNumber <= toLineNumber) { this._insertLinesAfter(ctx, fromLineNumber, toLineNumber, deltaTop, startLineNumber); @@ -435,9 +435,9 @@ class ViewLayerRenderer { } else if (ctx.rendLineNumberStart + ctx.linesLength - 1 > stopLineNumber) { // Remove lines after - let fromLineNumber = Math.max(0, stopLineNumber - ctx.rendLineNumberStart + 1); - let toLineNumber = ctx.linesLength - 1; - let removeCnt = toLineNumber - fromLineNumber + 1; + const fromLineNumber = Math.max(0, stopLineNumber - ctx.rendLineNumberStart + 1); + const toLineNumber = ctx.linesLength - 1; + const removeCnt = toLineNumber - fromLineNumber + 1; if (removeCnt > 0) { this._removeLinesAfter(ctx, removeCnt); @@ -455,13 +455,13 @@ class ViewLayerRenderer { const lines = ctx.lines; for (let i = startIndex; i <= endIndex; i++) { - let lineNumber = rendLineNumberStart + i; + const lineNumber = rendLineNumberStart + i; lines[i].layoutLine(lineNumber, deltaTop[lineNumber - deltaLN]); } } private _insertLinesBefore(ctx: IRendererContext, fromLineNumber: number, toLineNumber: number, deltaTop: number[], deltaLN: number): void { - let newLines: T[] = []; + const newLines: T[] = []; let newLinesLen = 0; for (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) { newLines[newLinesLen++] = this.host.createVisibleLine(); @@ -471,7 +471,7 @@ class ViewLayerRenderer { private _removeLinesBefore(ctx: IRendererContext, removeCount: number): void { for (let i = 0; i < removeCount; i++) { - let lineDomNode = ctx.lines[i].getDomNode(); + const lineDomNode = ctx.lines[i].getDomNode(); if (lineDomNode) { this.domNode.removeChild(lineDomNode); } @@ -480,7 +480,7 @@ class ViewLayerRenderer { } private _insertLinesAfter(ctx: IRendererContext, fromLineNumber: number, toLineNumber: number, deltaTop: number[], deltaLN: number): void { - let newLines: T[] = []; + const newLines: T[] = []; let newLinesLen = 0; for (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) { newLines[newLinesLen++] = this.host.createVisibleLine(); @@ -489,10 +489,10 @@ class ViewLayerRenderer { } private _removeLinesAfter(ctx: IRendererContext, removeCount: number): void { - let removeIndex = ctx.linesLength - removeCount; + const removeIndex = ctx.linesLength - removeCount; for (let i = 0; i < removeCount; i++) { - let lineDomNode = ctx.lines[removeIndex + i].getDomNode(); + const lineDomNode = ctx.lines[removeIndex + i].getDomNode(); if (lineDomNode) { this.domNode.removeChild(lineDomNode); } @@ -501,7 +501,7 @@ class ViewLayerRenderer { } private _finishRenderingNewLines(ctx: IRendererContext, domNodeIsEmpty: boolean, newLinesHTML: string, wasNew: boolean[]): void { - let lastChild = this.domNode.lastChild; + const lastChild = this.domNode.lastChild; if (domNodeIsEmpty || !lastChild) { this.domNode.innerHTML = newLinesHTML; } else { @@ -510,7 +510,7 @@ class ViewLayerRenderer { let currChild = this.domNode.lastChild; for (let i = ctx.linesLength - 1; i >= 0; i--) { - let line = ctx.lines[i]; + const line = ctx.lines[i]; if (wasNew[i]) { line.setDomNode(currChild); currChild = currChild.previousSibling; @@ -519,15 +519,15 @@ class ViewLayerRenderer { } private _finishRenderingInvalidLines(ctx: IRendererContext, invalidLinesHTML: string, wasInvalid: boolean[]): void { - let hugeDomNode = document.createElement('div'); + const hugeDomNode = document.createElement('div'); hugeDomNode.innerHTML = invalidLinesHTML; for (let i = 0; i < ctx.linesLength; i++) { - let line = ctx.lines[i]; + const line = ctx.lines[i]; if (wasInvalid[i]) { - let source = hugeDomNode.firstChild; - let lineDomNode = line.getDomNode()!; + const source = hugeDomNode.firstChild; + const lineDomNode = line.getDomNode()!; lineDomNode.parentNode!.replaceChild(source, lineDomNode); line.setDomNode(source); } @@ -543,7 +543,7 @@ class ViewLayerRenderer { const lines = ctx.lines; const rendLineNumberStart = ctx.rendLineNumberStart; - let wasNew: boolean[] = []; + const wasNew: boolean[] = []; { sb.reset(); let hadNewLine = false; @@ -577,10 +577,10 @@ class ViewLayerRenderer { sb.reset(); let hadInvalidLine = false; - let wasInvalid: boolean[] = []; + const wasInvalid: boolean[] = []; for (let i = 0; i < linesLength; i++) { - let line = lines[i]; + const line = lines[i]; wasInvalid[i] = false; if (wasNew[i]) { diff --git a/src/vs/editor/browser/view/viewOverlays.ts b/src/vs/editor/browser/view/viewOverlays.ts index 1adf5bcad62..82d89966fdb 100644 --- a/src/vs/editor/browser/view/viewOverlays.ts +++ b/src/vs/editor/browser/view/viewOverlays.ts @@ -40,7 +40,7 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost overlay.shouldRender()); + const toRender = this._dynamicOverlays.filter(overlay => overlay.shouldRender()); for (let i = 0, len = toRender.length; i < len; i++) { - let dynamicOverlay = toRender[i]; + const dynamicOverlay = toRender[i]; dynamicOverlay.prepareRender(ctx); dynamicOverlay.onDidRender(); } @@ -179,7 +179,7 @@ export class ViewOverlayLine implements IVisibleLine { public renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: IStringBuilder): boolean { let result = ''; for (let i = 0, len = this._dynamicOverlays.length; i < len; i++) { - let dynamicOverlay = this._dynamicOverlays[i]; + const dynamicOverlay = this._dynamicOverlays[i]; result += dynamicOverlay.render(viewportData.startLineNumber, lineNumber); } @@ -276,7 +276,7 @@ export class MarginViewOverlays extends ViewOverlays { _viewOverlaysRender(ctx: RestrictedRenderingContext): void { super._viewOverlaysRender(ctx); - let height = Math.min(ctx.scrollHeight, 1000000); + const height = Math.min(ctx.scrollHeight, 1000000); this.domNode.setHeight(height); this.domNode.setWidth(this._contentLeft); } diff --git a/src/vs/editor/browser/view/viewPart.ts b/src/vs/editor/browser/view/viewPart.ts index 319ce014e58..a821807408b 100644 --- a/src/vs/editor/browser/view/viewPart.ts +++ b/src/vs/editor/browser/view/viewPart.ts @@ -50,7 +50,7 @@ export class PartFingerprints { } public static read(target: Element): PartFingerprint { - let r = target.getAttribute('data-mprt'); + const r = target.getAttribute('data-mprt'); if (r === null) { return PartFingerprint.None; } @@ -70,7 +70,7 @@ export class PartFingerprints { child = child.parentElement; } - let r = new Uint8Array(resultLen); + const r = new Uint8Array(resultLen); for (let i = 0; i < resultLen; i++) { r[i] = result[resultLen - i - 1]; } diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index d31268fdf88..f5b27f92188 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -59,7 +59,7 @@ export class ViewContentWidgets extends ViewPart { // --- begin event handlers public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (const widgetId of keys) { this._widgets[widgetId].onConfigurationChanged(e); } @@ -73,7 +73,7 @@ export class ViewContentWidgets extends ViewPart { return true; } public onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): boolean { - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (const widgetId of keys) { this._widgets[widgetId].onLineMappingChanged(e); } @@ -139,21 +139,21 @@ export class ViewContentWidgets extends ViewPart { } public onBeforeRender(viewportData: ViewportData): void { - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (const widgetId of keys) { this._widgets[widgetId].onBeforeRender(viewportData); } } public prepareRender(ctx: RenderingContext): void { - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (const widgetId of keys) { this._widgets[widgetId].prepareRender(ctx); } } public render(ctx: RestrictedRenderingContext): void { - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (const widgetId of keys) { this._widgets[widgetId].render(ctx); } @@ -280,17 +280,17 @@ class Widget { // Our visible box is split horizontally by the current line => 2 boxes // a) the box above the line - let aboveLineTop = topLeft.top; - let heightAboveLine = aboveLineTop; + const aboveLineTop = topLeft.top; + const heightAboveLine = aboveLineTop; // b) the box under the line - let underLineTop = bottomLeft.top + this._lineHeight; - let heightUnderLine = ctx.viewportHeight - underLineTop; + const underLineTop = bottomLeft.top + this._lineHeight; + const heightUnderLine = ctx.viewportHeight - underLineTop; - let aboveTop = aboveLineTop - height; - let fitsAbove = (heightAboveLine >= height); - let belowTop = underLineTop; - let fitsBelow = (heightUnderLine >= height); + const aboveTop = aboveLineTop - height; + const fitsAbove = (heightAboveLine >= height); + const belowTop = underLineTop; + const fitsBelow = (heightUnderLine >= height); // And its left let actualAboveLeft = topLeft.left; @@ -320,8 +320,8 @@ class Widget { } private _layoutBoxInPage(topLeft: Coordinate, bottomLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult | null { - let aboveLeft0 = topLeft.left - ctx.scrollLeft; - let belowLeft0 = bottomLeft.left - ctx.scrollLeft; + const aboveLeft0 = topLeft.left - ctx.scrollLeft; + const belowLeft0 = bottomLeft.left - ctx.scrollLeft; if (aboveLeft0 < 0 || aboveLeft0 > this._contentWidth) { // Don't render if position is scrolled outside viewport @@ -333,39 +333,39 @@ class Widget { let aboveLeft = aboveLeft0 + this._contentLeft; let belowLeft = belowLeft0 + this._contentLeft; - let domNodePosition = dom.getDomNodePagePosition(this._viewDomNode.domNode); - let absoluteAboveTop = domNodePosition.top + aboveTop - dom.StandardWindow.scrollY; - let absoluteBelowTop = domNodePosition.top + belowTop - dom.StandardWindow.scrollY; + const domNodePosition = dom.getDomNodePagePosition(this._viewDomNode.domNode); + const absoluteAboveTop = domNodePosition.top + aboveTop - dom.StandardWindow.scrollY; + const absoluteBelowTop = domNodePosition.top + belowTop - dom.StandardWindow.scrollY; let absoluteAboveLeft = domNodePosition.left + aboveLeft - dom.StandardWindow.scrollX; let absoluteBelowLeft = domNodePosition.left + belowLeft - dom.StandardWindow.scrollX; - let INNER_WIDTH = window.innerWidth || document.documentElement!.clientWidth || document.body.clientWidth; - let INNER_HEIGHT = window.innerHeight || document.documentElement!.clientHeight || document.body.clientHeight; + const INNER_WIDTH = window.innerWidth || document.documentElement!.clientWidth || document.body.clientWidth; + const INNER_HEIGHT = window.innerHeight || document.documentElement!.clientHeight || document.body.clientHeight; // Leave some clearance to the bottom - let TOP_PADDING = 22; - let BOTTOM_PADDING = 22; + const TOP_PADDING = 22; + const BOTTOM_PADDING = 22; - let fitsAbove = (absoluteAboveTop >= TOP_PADDING), + const fitsAbove = (absoluteAboveTop >= TOP_PADDING), fitsBelow = (absoluteBelowTop + height <= INNER_HEIGHT - BOTTOM_PADDING); if (absoluteAboveLeft + width + 20 > INNER_WIDTH) { - let delta = absoluteAboveLeft - (INNER_WIDTH - width - 20); + const delta = absoluteAboveLeft - (INNER_WIDTH - width - 20); absoluteAboveLeft -= delta; aboveLeft -= delta; } if (absoluteBelowLeft + width + 20 > INNER_WIDTH) { - let delta = absoluteBelowLeft - (INNER_WIDTH - width - 20); + const delta = absoluteBelowLeft - (INNER_WIDTH - width - 20); absoluteBelowLeft -= delta; belowLeft -= delta; } if (absoluteAboveLeft < 0) { - let delta = absoluteAboveLeft; + const delta = absoluteAboveLeft; absoluteAboveLeft -= delta; aboveLeft -= delta; } if (absoluteBelowLeft < 0) { - let delta = absoluteBelowLeft; + const delta = absoluteBelowLeft; absoluteBelowLeft -= delta; belowLeft -= delta; } diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index 7f4500dfb73..a6ecaf390eb 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -69,12 +69,12 @@ export class DecorationsOverlay extends DynamicViewOverlay { // --- end event handlers public prepareRender(ctx: RenderingContext): void { - let _decorations = ctx.getDecorationsInViewport(); + const _decorations = ctx.getDecorationsInViewport(); // Keep only decorations with `className` let decorations: ViewModelDecoration[] = [], decorationsLen = 0; for (let i = 0, len = _decorations.length; i < len; i++) { - let d = _decorations[i]; + const d = _decorations[i]; if (d.options.className) { decorations[decorationsLen++] = d; } @@ -101,11 +101,11 @@ export class DecorationsOverlay extends DynamicViewOverlay { return Range.compareRangesUsingStarts(a.range, b.range); }); - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; - let output: string[] = []; + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; + const lineIndex = lineNumber - visibleStartLineNumber; output[lineIndex] = ''; } @@ -116,18 +116,18 @@ export class DecorationsOverlay extends DynamicViewOverlay { } private _renderWholeLineDecorations(ctx: RenderingContext, decorations: ViewModelDecoration[], output: string[]): void { - let lineHeight = String(this._lineHeight); - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const lineHeight = String(this._lineHeight); + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; for (let i = 0, lenI = decorations.length; i < lenI; i++) { - let d = decorations[i]; + const d = decorations[i]; if (!d.options.isWholeLine) { continue; } - let decorationOutput = ( + const decorationOutput = ( '
' ); - let startLineNumber = Math.max(d.range.startLineNumber, visibleStartLineNumber); - let endLineNumber = Math.min(d.range.endLineNumber, visibleEndLineNumber); + const startLineNumber = Math.max(d.range.startLineNumber, visibleStartLineNumber); + const endLineNumber = Math.min(d.range.endLineNumber, visibleEndLineNumber); for (let j = startLineNumber; j <= endLineNumber; j++) { - let lineIndex = j - visibleStartLineNumber; + const lineIndex = j - visibleStartLineNumber; output[lineIndex] += decorationOutput; } } @@ -189,13 +189,13 @@ export class DecorationsOverlay extends DynamicViewOverlay { } private _renderNormalDecoration(ctx: RenderingContext, range: Range, className: string, showIfCollapsed: boolean, lineHeight: string, visibleStartLineNumber: number, output: string[]): void { - let linesVisibleRanges = ctx.linesVisibleRangesForRange(range, /*TODO@Alex*/className === 'findMatch'); + const linesVisibleRanges = ctx.linesVisibleRangesForRange(range, /*TODO@Alex*/className === 'findMatch'); if (!linesVisibleRanges) { return; } for (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) { - let lineVisibleRanges = linesVisibleRanges[j]; + const lineVisibleRanges = linesVisibleRanges[j]; const lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber; if (showIfCollapsed && lineVisibleRanges.ranges.length === 1) { @@ -228,7 +228,7 @@ export class DecorationsOverlay extends DynamicViewOverlay { if (!this._renderResult) { return ''; } - let lineIndex = lineNumber - startLineNumber; + const lineIndex = lineNumber - startLineNumber; if (lineIndex < 0 || lineIndex >= this._renderResult.length) { return ''; } diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts index 8ead82c249a..add801b30ee 100644 --- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts +++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts @@ -31,7 +31,7 @@ export class EditorScrollbar extends ViewPart { const editor = this._context.configuration.editor; const configScrollbarOpts = editor.viewInfo.scrollbar; - let scrollbarOptions: ScrollableElementCreationOptions = { + const scrollbarOptions: ScrollableElementCreationOptions = { listenOnDomNode: viewDomNode.domNode, className: 'editor-scrollable' + ' ' + getThemeTypeSelector(context.theme.type), useShadows: false, @@ -62,11 +62,11 @@ export class EditorScrollbar extends ViewPart { // the browser will try desperately to reveal that dom node, unexpectedly // changing the .scrollTop of this.linesContent - let onBrowserDesperateReveal = (domNode: HTMLElement, lookAtScrollTop: boolean, lookAtScrollLeft: boolean) => { - let newScrollPosition: INewScrollPosition = {}; + const onBrowserDesperateReveal = (domNode: HTMLElement, lookAtScrollTop: boolean, lookAtScrollLeft: boolean) => { + const newScrollPosition: INewScrollPosition = {}; if (lookAtScrollTop) { - let deltaTop = domNode.scrollTop; + const deltaTop = domNode.scrollTop; if (deltaTop) { newScrollPosition.scrollTop = this._context.viewLayout.getCurrentScrollTop() + deltaTop; domNode.scrollTop = 0; @@ -74,7 +74,7 @@ export class EditorScrollbar extends ViewPart { } if (lookAtScrollLeft) { - let deltaLeft = domNode.scrollLeft; + const deltaLeft = domNode.scrollLeft; if (deltaLeft) { newScrollPosition.scrollLeft = this._context.viewLayout.getCurrentScrollLeft() + deltaLeft; domNode.scrollLeft = 0; @@ -126,7 +126,7 @@ export class EditorScrollbar extends ViewPart { public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { if (e.viewInfo) { const editor = this._context.configuration.editor; - let newOpts: ScrollableElementChangeOptions = { + const newOpts: ScrollableElementChangeOptions = { handleMouseWheel: editor.viewInfo.scrollbar.handleMouseWheel, mouseWheelScrollSensitivity: editor.viewInfo.scrollbar.mouseWheelScrollSensitivity, fastScrollSensitivity: editor.viewInfo.scrollbar.fastScrollSensitivity diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index 585dd754a7e..baf374971fb 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -27,9 +27,9 @@ export abstract class DedupOverlay extends DynamicViewOverlay { protected _render(visibleStartLineNumber: number, visibleEndLineNumber: number, decorations: DecorationToRender[]): string[][] { - let output: string[][] = []; + const output: string[][] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; + const lineIndex = lineNumber - visibleStartLineNumber; output[lineIndex] = []; } @@ -50,10 +50,10 @@ export abstract class DedupOverlay extends DynamicViewOverlay { let prevClassName: string | null = null; let prevEndLineIndex = 0; for (let i = 0, len = decorations.length; i < len; i++) { - let d = decorations[i]; - let className = d.className; + const d = decorations[i]; + const className = d.className; let startLineIndex = Math.max(d.startLineNumber, visibleStartLineNumber) - visibleStartLineNumber; - let endLineIndex = Math.min(d.endLineNumber, visibleEndLineNumber) - visibleStartLineNumber; + const endLineIndex = Math.min(d.endLineNumber, visibleEndLineNumber) - visibleStartLineNumber; if (prevClassName === className) { startLineIndex = Math.max(prevEndLineIndex + 1, startLineIndex); @@ -138,11 +138,11 @@ export class GlyphMarginOverlay extends DedupOverlay { // --- end event handlers protected _getDecorations(ctx: RenderingContext): DecorationToRender[] { - let decorations = ctx.getDecorationsInViewport(); + const decorations = ctx.getDecorationsInViewport(); let r: DecorationToRender[] = [], rLen = 0; for (let i = 0, len = decorations.length; i < len; i++) { - let d = decorations[i]; - let glyphMarginClassName = d.options.glyphMarginClassName; + const d = decorations[i]; + const glyphMarginClassName = d.options.glyphMarginClassName; if (glyphMarginClassName) { r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, glyphMarginClassName); } @@ -156,19 +156,19 @@ export class GlyphMarginOverlay extends DedupOverlay { return; } - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; - let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx)); + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx)); - let lineHeight = this._lineHeight.toString(); - let left = this._glyphMarginLeft.toString(); - let width = this._glyphMarginWidth.toString(); - let common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;">'; + const lineHeight = this._lineHeight.toString(); + const left = this._glyphMarginLeft.toString(); + const width = this._glyphMarginWidth.toString(); + const common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;">'; - let output: string[] = []; + const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; - let classNames = toRender[lineIndex]; + const lineIndex = lineNumber - visibleStartLineNumber; + const classNames = toRender[lineIndex]; if (classNames.length === 0) { output[lineIndex] = ''; @@ -188,7 +188,7 @@ export class GlyphMarginOverlay extends DedupOverlay { if (!this._renderResult) { return ''; } - let lineIndex = lineNumber - startLineNumber; + const lineIndex = lineNumber - startLineNumber; if (lineIndex < 0 || lineIndex >= this._renderResult.length) { return ''; } diff --git a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts index 7a7e613f1e7..bc1373afe48 100644 --- a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts +++ b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts @@ -120,17 +120,17 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { activeIndentLevel = activeIndentInfo.indent; } - let output: string[] = []; + const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { const containsActiveIndentGuide = (activeIndentStartLineNumber <= lineNumber && lineNumber <= activeIndentEndLineNumber); const lineIndex = lineNumber - visibleStartLineNumber; const indent = indents[lineIndex]; let result = ''; - let leftMostVisiblePosition = ctx.visibleRangeForPosition(new Position(lineNumber, 1)); + const leftMostVisiblePosition = ctx.visibleRangeForPosition(new Position(lineNumber, 1)); let left = leftMostVisiblePosition ? leftMostVisiblePosition.left : 0; for (let i = 1; i <= indent; i++) { - let className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr'); + const className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr'); result += `
`; left += indentWidth; if (left > scrollWidth) { @@ -147,7 +147,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { if (!this._renderResult) { return ''; } - let lineIndex = lineNumber - startLineNumber; + const lineIndex = lineNumber - startLineNumber; if (lineIndex < 0 || lineIndex >= this._renderResult.length) { return ''; } diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts index 7bd48eed211..79404907337 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts @@ -97,7 +97,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { if (modelPosition.column !== 1) { return ''; } - let modelLineNumber = modelPosition.lineNumber; + const modelLineNumber = modelPosition.lineNumber; if (!this._renderFinalNewline) { const lineCount = this._context.model.getLineCount(); @@ -113,7 +113,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { } if (this._renderLineNumbers === RenderLineNumbersType.Relative) { - let diff = Math.abs(this._lastCursorModelPosition.lineNumber - modelLineNumber); + const diff = Math.abs(this._lastCursorModelPosition.lineNumber - modelLineNumber); if (diff === 0) { return '' + modelLineNumber + ''; } @@ -139,16 +139,16 @@ export class LineNumbersOverlay extends DynamicViewOverlay { return; } - let lineHeightClassName = (platform.isLinux ? (this._lineHeight % 2 === 0 ? ' lh-even' : ' lh-odd') : ''); - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; - let common = '
'; + const lineHeightClassName = (platform.isLinux ? (this._lineHeight % 2 === 0 ? ' lh-even' : ' lh-odd') : ''); + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const common = '
'; - let output: string[] = []; + const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; + const lineIndex = lineNumber - visibleStartLineNumber; - let renderLineNumber = this._getLineRenderLineNumber(lineNumber); + const renderLineNumber = this._getLineRenderLineNumber(lineNumber); if (renderLineNumber) { output[lineIndex] = ( @@ -168,7 +168,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { if (!this._renderResult) { return ''; } - let lineIndex = lineNumber - startLineNumber; + const lineIndex = lineNumber - startLineNumber; if (lineIndex < 0 || lineIndex >= this._renderResult.length) { return ''; } diff --git a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts index 218418ad05a..1561687a35e 100644 --- a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts +++ b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts @@ -49,7 +49,7 @@ export class RangeUtil { } private static _readClientRects(startElement: Node, startOffset: number, endElement: Node, endOffset: number, endNode: HTMLElement): ClientRectList | DOMRectList | null { - let range = this._createRange(); + const range = this._createRange(); try { range.setStart(startElement, startOffset); range.setEnd(endElement, endOffset); @@ -102,7 +102,7 @@ export class RangeUtil { // We go through FloatHorizontalRange because it has been observed in bi-di text // that the clientRects are not coming in sorted from the browser - let result: FloatHorizontalRange[] = []; + const result: FloatHorizontalRange[] = []; for (let i = 0, len = clientRects.length; i < len; i++) { const clientRect = clientRects[i]; result[i] = new FloatHorizontalRange(Math.max(0, clientRect.left - clientRectDeltaLeft), clientRect.width); @@ -113,8 +113,8 @@ export class RangeUtil { public static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, endNode: HTMLElement): HorizontalRange[] | null { // Panic check - let min = 0; - let max = domNode.children.length - 1; + const min = 0; + const max = domNode.children.length - 1; if (min > max) { return null; } @@ -152,7 +152,7 @@ export class RangeUtil { startOffset = Math.min(startElement.textContent!.length, Math.max(0, startOffset)); endOffset = Math.min(endElement.textContent!.length, Math.max(0, endOffset)); - let clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode); + const clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode); return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft); } } diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 67a3cfc6392..ab8934477c9 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -180,8 +180,8 @@ export class ViewLine implements IVisibleLine { continue; } - let startColumn = (selection.startLineNumber === lineNumber ? selection.startColumn : lineData.minColumn); - let endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn); + const startColumn = (selection.startLineNumber === lineNumber ? selection.startColumn : lineData.minColumn); + const endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn); if (startColumn < endColumn) { actualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', InlineDecorationType.Regular)); @@ -189,7 +189,7 @@ export class ViewLine implements IVisibleLine { } } - let renderLineInput = new RenderLineInput( + const renderLineInput = new RenderLineInput( options.useMonospaceOptimizations, options.canUseHalfwidthRightwardsArrow, lineData.content, @@ -369,7 +369,7 @@ class FastRenderedViewLine implements IRenderedViewLine { } public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number { - let spanNodeTextContentLength = spanNode.textContent!.length; + const spanNodeTextContentLength = spanNode.textContent!.length; let spanIndex = -1; while (spanNode) { @@ -377,7 +377,7 @@ class FastRenderedViewLine implements IRenderedViewLine { spanIndex++; } - let charOffset = this._characterMapping.partDataToCharOffset(spanIndex, spanNodeTextContentLength, offset); + const charOffset = this._characterMapping.partDataToCharOffset(spanIndex, spanNodeTextContentLength, offset); return charOffset + 1; } } @@ -446,12 +446,12 @@ class RenderedViewLine implements IRenderedViewLine { public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null { if (this._pixelOffsetCache !== null) { // the text is LTR - let startOffset = this._readPixelOffset(startColumn, context); + const startOffset = this._readPixelOffset(startColumn, context); if (startOffset === -1) { return null; } - let endOffset = this._readPixelOffset(endColumn, context); + const endOffset = this._readPixelOffset(endColumn, context); if (endOffset === -1) { return null; } @@ -464,7 +464,7 @@ class RenderedViewLine implements IRenderedViewLine { protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null { if (startColumn === endColumn) { - let pixelOffset = this._readPixelOffset(startColumn, context); + const pixelOffset = this._readPixelOffset(startColumn, context); if (pixelOffset === -1) { return null; } else { @@ -495,12 +495,12 @@ class RenderedViewLine implements IRenderedViewLine { if (this._pixelOffsetCache !== null) { // the text is LTR - let cachedPixelOffset = this._pixelOffsetCache[column]; + const cachedPixelOffset = this._pixelOffsetCache[column]; if (cachedPixelOffset !== -1) { return cachedPixelOffset; } - let result = this._actualReadPixelOffset(column, context); + const result = this._actualReadPixelOffset(column, context); this._pixelOffsetCache[column] = result; return result; } @@ -511,7 +511,7 @@ class RenderedViewLine implements IRenderedViewLine { private _actualReadPixelOffset(column: number, context: DomReadingContext): number { if (this._characterMapping.length === 0) { // This line has no content - let r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), 0, 0, 0, 0, context.clientRectDeltaLeft, context.endNode); + const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), 0, 0, 0, 0, context.clientRectDeltaLeft, context.endNode); if (!r || r.length === 0) { return -1; } @@ -523,11 +523,11 @@ class RenderedViewLine implements IRenderedViewLine { return this.getWidth(); } - let partData = this._characterMapping.charOffsetToPartData(column - 1); - let partIndex = CharacterMapping.getPartIndex(partData); - let charOffsetInPart = CharacterMapping.getCharIndex(partData); + const partData = this._characterMapping.charOffsetToPartData(column - 1); + const partIndex = CharacterMapping.getPartIndex(partData); + const charOffsetInPart = CharacterMapping.getCharIndex(partData); - let r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), partIndex, charOffsetInPart, partIndex, charOffsetInPart, context.clientRectDeltaLeft, context.endNode); + const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), partIndex, charOffsetInPart, partIndex, charOffsetInPart, context.clientRectDeltaLeft, context.endNode); if (!r || r.length === 0) { return -1; } @@ -542,13 +542,13 @@ class RenderedViewLine implements IRenderedViewLine { return [new HorizontalRange(0, this.getWidth())]; } - let startPartData = this._characterMapping.charOffsetToPartData(startColumn - 1); - let startPartIndex = CharacterMapping.getPartIndex(startPartData); - let startCharOffsetInPart = CharacterMapping.getCharIndex(startPartData); + const startPartData = this._characterMapping.charOffsetToPartData(startColumn - 1); + const startPartIndex = CharacterMapping.getPartIndex(startPartData); + const startCharOffsetInPart = CharacterMapping.getCharIndex(startPartData); - let endPartData = this._characterMapping.charOffsetToPartData(endColumn - 1); - let endPartIndex = CharacterMapping.getPartIndex(endPartData); - let endCharOffsetInPart = CharacterMapping.getCharIndex(endPartData); + const endPartData = this._characterMapping.charOffsetToPartData(endColumn - 1); + const endPartIndex = CharacterMapping.getPartIndex(endPartData); + const endCharOffsetInPart = CharacterMapping.getCharIndex(endPartData); return RangeUtil.readHorizontalRanges(this._getReadingTarget(), startPartIndex, startCharOffsetInPart, endPartIndex, endCharOffsetInPart, context.clientRectDeltaLeft, context.endNode); } @@ -557,7 +557,7 @@ class RenderedViewLine implements IRenderedViewLine { * Returns the column for the text found at a specific offset inside a rendered dom node */ public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number { - let spanNodeTextContentLength = spanNode.textContent!.length; + const spanNodeTextContentLength = spanNode.textContent!.length; let spanIndex = -1; while (spanNode) { @@ -565,14 +565,14 @@ class RenderedViewLine implements IRenderedViewLine { spanIndex++; } - let charOffset = this._characterMapping.partDataToCharOffset(spanIndex, spanNodeTextContentLength, offset); + const charOffset = this._characterMapping.partDataToCharOffset(spanIndex, spanNodeTextContentLength, offset); return charOffset + 1; } } class WebKitRenderedViewLine extends RenderedViewLine { protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null { - let output = super._readVisibleRangesForRange(startColumn, endColumn, context); + const output = super._readVisibleRangesForRange(startColumn, endColumn, context); if (!output || output.length === 0 || startColumn === endColumn || (startColumn === 1 && endColumn === this._characterMapping.length)) { return output; @@ -583,9 +583,9 @@ class WebKitRenderedViewLine extends RenderedViewLine { if (!this.input.containsRTL) { // This is an attempt to patch things up // Find position of last column - let endPixelOffset = this._readPixelOffset(endColumn, context); + const endPixelOffset = this._readPixelOffset(endColumn, context); if (endPixelOffset !== -1) { - let lastRange = output[output.length - 1]; + const lastRange = output[output.length - 1]; if (lastRange.left < endPixelOffset) { // Trim down the width of the last visible range to not go after the last column's position lastRange.width = endPixelOffset - lastRange.left; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index b09c5536dec..136d50501ab 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -169,14 +169,14 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, private _onOptionsMaybeChanged(): boolean { const conf = this._context.configuration; - let newViewLineOptions = new ViewLineOptions(conf, this._context.theme.type); + const newViewLineOptions = new ViewLineOptions(conf, this._context.theme.type); if (!this._viewLineOptions.equals(newViewLineOptions)) { this._viewLineOptions = newViewLineOptions; - let startLineNumber = this._visibleLines.getStartLineNumber(); - let endLineNumber = this._visibleLines.getEndLineNumber(); + const startLineNumber = this._visibleLines.getStartLineNumber(); + const endLineNumber = this._visibleLines.getEndLineNumber(); for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) { - let line = this._visibleLines.getVisibleLine(lineNumber); + const line = this._visibleLines.getVisibleLine(lineNumber); line.onOptionsChanged(this._viewLineOptions); } return true; @@ -185,8 +185,8 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, return false; } public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); let r = false; for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) { r = this._visibleLines.getVisibleLine(lineNumber).onSelectionChanged() || r; @@ -195,8 +195,8 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, } public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { if (true/*e.inlineDecorationsChanged*/) { - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) { this._visibleLines.getVisibleLine(lineNumber).onDecorationsChanged(); } @@ -204,7 +204,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, return true; } public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { - let shouldRender = this._visibleLines.onFlushed(e); + const shouldRender = this._visibleLines.onFlushed(e); this._maxLineWidth = 0; return shouldRender; } @@ -282,12 +282,12 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, // ----------- HELPERS FOR OTHERS public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null { - let viewLineDomNode = this._getViewLineDomNode(spanNode); + const viewLineDomNode = this._getViewLineDomNode(spanNode); if (viewLineDomNode === null) { // Couldn't find view line node return null; } - let lineNumber = this._getLineNumberFor(viewLineDomNode); + const lineNumber = this._getLineNumberFor(viewLineDomNode); if (lineNumber === -1) { // Couldn't find view line node @@ -304,15 +304,15 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, return new Position(lineNumber, 1); } - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) { // Couldn't find line return null; } let column = this._visibleLines.getVisibleLine(lineNumber).getColumnOfNodeOffset(lineNumber, spanNode, offset); - let minColumn = this._context.model.getLineMinColumn(lineNumber); + const minColumn = this._context.model.getLineMinColumn(lineNumber); if (column < minColumn) { column = minColumn; } @@ -333,10 +333,10 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, * @returns the line number of this view line dom node. */ private _getLineNumberFor(domNode: HTMLElement): number { - let startLineNumber = this._visibleLines.getStartLineNumber(); - let endLineNumber = this._visibleLines.getEndLineNumber(); + const startLineNumber = this._visibleLines.getStartLineNumber(); + const endLineNumber = this._visibleLines.getEndLineNumber(); for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) { - let line = this._visibleLines.getVisibleLine(lineNumber); + const line = this._visibleLines.getVisibleLine(lineNumber); if (domNode === line.getDomNode()) { return lineNumber; } @@ -345,8 +345,8 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, } public getLineWidth(lineNumber: number): number { - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) { // Couldn't find line return -1; @@ -362,38 +362,38 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, return null; } - let originalEndLineNumber = _range.endLineNumber; + const originalEndLineNumber = _range.endLineNumber; const range = Range.intersectRanges(_range, this._lastRenderedData.getCurrentVisibleRange()); if (!range) { return null; } let visibleRanges: LineVisibleRanges[] = [], visibleRangesLen = 0; - let domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot); + const domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot); let nextLineModelLineNumber: number = 0; if (includeNewLines) { nextLineModelLineNumber = this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new Position(range.startLineNumber, 1)).lineNumber; } - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) { if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) { continue; } - let startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1; - let endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber); - let visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext); + const startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1; + const endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber); + const visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext); if (!visibleRangesForLine || visibleRangesForLine.length === 0) { continue; } if (includeNewLines && lineNumber < originalEndLineNumber) { - let currentLineModelLineNumber = nextLineModelLineNumber; + const currentLineModelLineNumber = nextLineModelLineNumber; nextLineModelLineNumber = this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new Position(lineNumber + 1, 1)).lineNumber; if (currentLineModelLineNumber !== nextLineModelLineNumber) { @@ -425,19 +425,19 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, } let result: HorizontalRange[] = []; - let domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot); + const domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot); - let rendStartLineNumber = this._visibleLines.getStartLineNumber(); - let rendEndLineNumber = this._visibleLines.getEndLineNumber(); + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) { if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) { continue; } - let startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1; - let endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber); - let visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext); + const startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1; + const endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber); + const visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext); if (!visibleRangesForLine || visibleRangesForLine.length === 0) { continue; @@ -542,9 +542,9 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, this.onDidRender(); // compute new scroll position - let newScrollLeft = this._computeScrollLeftToRevealRange(revealLineNumber, revealStartColumn, revealEndColumn); + const newScrollLeft = this._computeScrollLeftToRevealRange(revealLineNumber, revealStartColumn, revealEndColumn); - let isViewportWrapping = this._isViewportWrapping; + const isViewportWrapping = this._isViewportWrapping; if (!isViewportWrapping) { // ensure `scrollWidth` is large enough this._ensureMaxLineWidth(newScrollLeft.maxHorizontalOffset); @@ -579,7 +579,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, // --- width private _ensureMaxLineWidth(lineWidth: number): void { - let iLineWidth = Math.ceil(lineWidth); + const iLineWidth = Math.ceil(lineWidth); if (this._maxLineWidth < iLineWidth) { this._maxLineWidth = iLineWidth; this._context.viewLayout.onMaxLineWidthChanged(this._maxLineWidth); @@ -587,9 +587,9 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, } private _computeScrollTopToRevealRange(viewport: Viewport, range: Range, verticalType: viewEvents.VerticalRevealType): number { - let viewportStartY = viewport.top; - let viewportHeight = viewport.height; - let viewportEndY = viewportStartY + viewportHeight; + const viewportStartY = viewport.top; + const viewportHeight = viewport.height; + const viewportEndY = viewportStartY + viewportHeight; let boxStartY: number; let boxEndY: number; @@ -609,7 +609,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, newScrollTop = viewportStartY; } else { // Box is outside the viewport... center it - let boxMiddleY = (boxStartY + boxEndY) / 2; + const boxMiddleY = (boxStartY + boxEndY) / 2; newScrollTop = Math.max(0, boxMiddleY - viewportHeight / 2); } } else { @@ -623,11 +623,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, let maxHorizontalOffset = 0; - let viewport = this._context.viewLayout.getCurrentViewport(); - let viewportStartX = viewport.left; - let viewportEndX = viewportStartX + viewport.width; + const viewport = this._context.viewLayout.getCurrentViewport(); + const viewportStartX = viewport.left; + const viewportEndX = viewportStartX + viewport.width; - let visibleRanges = this.visibleRangesForRange2(new Range(lineNumber, startColumn, lineNumber, endColumn)); + const visibleRanges = this.visibleRangesForRange2(new Range(lineNumber, startColumn, lineNumber, endColumn)); let boxStartX = Number.MAX_VALUE; let boxEndX = 0; @@ -653,7 +653,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, boxStartX = Math.max(0, boxStartX - ViewLines.HORIZONTAL_EXTRA_PX); boxEndX += this._revealHorizontalRightPadding; - let newScrollLeft = this._computeMinimumScrolling(viewportStartX, viewportEndX, boxStartX, boxEndX); + const newScrollLeft = this._computeMinimumScrolling(viewportStartX, viewportEndX, boxStartX, boxEndX); return { scrollLeft: newScrollLeft, maxHorizontalOffset: maxHorizontalOffset @@ -668,8 +668,8 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, revealAtStart = !!revealAtStart; revealAtEnd = !!revealAtEnd; - let viewportLength = viewportEnd - viewportStart; - let boxLength = boxEnd - boxStart; + const viewportLength = viewportEnd - viewportStart; + const boxLength = boxEnd - boxStart; if (boxLength < viewportLength) { // The box would fit in the viewport diff --git a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts index 5a0937df3ba..1dec064a1ba 100644 --- a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts +++ b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts @@ -66,11 +66,11 @@ export class LinesDecorationsOverlay extends DedupOverlay { // --- end event handlers protected _getDecorations(ctx: RenderingContext): DecorationToRender[] { - let decorations = ctx.getDecorationsInViewport(); + const decorations = ctx.getDecorationsInViewport(); let r: DecorationToRender[] = [], rLen = 0; for (let i = 0, len = decorations.length; i < len; i++) { - let d = decorations[i]; - let linesDecorationsClassName = d.options.linesDecorationsClassName; + const d = decorations[i]; + const linesDecorationsClassName = d.options.linesDecorationsClassName; if (linesDecorationsClassName) { r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName); } @@ -79,18 +79,18 @@ export class LinesDecorationsOverlay extends DedupOverlay { } public prepareRender(ctx: RenderingContext): void { - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; - let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx)); + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx)); - let left = this._decorationsLeft.toString(); - let width = this._decorationsWidth.toString(); - let common = '" style="left:' + left + 'px;width:' + width + 'px;">
'; + const left = this._decorationsLeft.toString(); + const width = this._decorationsWidth.toString(); + const common = '" style="left:' + left + 'px;width:' + width + 'px;">
'; - let output: string[] = []; + const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; - let classNames = toRender[lineIndex]; + const lineIndex = lineNumber - visibleStartLineNumber; + const classNames = toRender[lineIndex]; let lineOutput = ''; for (let i = 0, len = classNames.length; i < len; i++) { lineOutput += '
'; diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 789924de50f..25970859495 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -200,7 +200,7 @@ class MinimapLayout { * Compute a desired `scrollPosition` such that the slider moves by `delta`. */ public getDesiredScrollTopFromDelta(delta: number): number { - let desiredSliderPosition = this.sliderTop + delta; + const desiredSliderPosition = this.sliderTop + delta; return Math.round(desiredSliderPosition / this._computedSliderRatio); } @@ -350,7 +350,7 @@ class RenderData { } _get(): { imageData: ImageData; rendLineNumberStart: number; lines: MinimapLine[]; } { - let tmp = this._renderedLines._get(); + const tmp = this._renderedLines._get(); return { imageData: this._imageData, rendLineNumberStart: tmp.rendLineNumberStart, @@ -396,7 +396,7 @@ class MinimapBuffers { public getBuffer(): ImageData { // rotate buffers this._lastUsedBuffer = 1 - this._lastUsedBuffer; - let result = this._buffers[this._lastUsedBuffer]; + const result = this._buffers[this._lastUsedBuffer]; // fill with background color result.data.set(this._backgroundFillData); @@ -409,7 +409,7 @@ class MinimapBuffers { const backgroundG = background.g; const backgroundB = background.b; - let result = new Uint8ClampedArray(WIDTH * HEIGHT * 4); + const result = new Uint8ClampedArray(WIDTH * HEIGHT * 4); let offset = 0; for (let i = 0; i < HEIGHT; i++) { for (let j = 0; j < WIDTH; j++) { @@ -584,7 +584,7 @@ export class Minimap extends ViewPart { } private _onOptionsMaybeChanged(): boolean { - let opts = new MinimapOptions(this._context.configuration); + const opts = new MinimapOptions(this._context.configuration); if (this._options.equals(opts)) { return false; } @@ -721,7 +721,7 @@ export class Minimap extends ViewPart { // Render the rest of lines let dy = 0; - let renderedLines: MinimapLine[] = []; + const renderedLines: MinimapLine[] = []; for (let lineIndex = 0, lineCount = endLineNumber - startLineNumber + 1; lineIndex < lineCount; lineIndex++) { if (needed[lineIndex]) { Minimap._renderLine( @@ -764,7 +764,7 @@ export class Minimap extends ViewPart { lastRenderData: RenderData | null, ): [number, number, boolean[]] { - let needed: boolean[] = []; + const needed: boolean[] = []; if (!lastRenderData) { for (let i = 0, len = endLineNumber - startLineNumber + 1; i < len; i++) { needed[i] = true; @@ -801,10 +801,10 @@ export class Minimap extends ViewPart { continue; } - let sourceStart = source_dy * WIDTH * 4; - let sourceEnd = (source_dy + minimapLineHeight) * WIDTH * 4; - let destStart = dest_dy * WIDTH * 4; - let destEnd = (dest_dy + minimapLineHeight) * WIDTH * 4; + const sourceStart = source_dy * WIDTH * 4; + const sourceEnd = (source_dy + minimapLineHeight) * WIDTH * 4; + const destStart = dest_dy * WIDTH * 4; + const destEnd = (dest_dy + minimapLineHeight) * WIDTH * 4; if (copySourceEnd === sourceStart && copyDestEnd === destStart) { // contiguous zone => extend copy request @@ -881,7 +881,7 @@ export class Minimap extends ViewPart { const charCode = content.charCodeAt(charIndex); if (charCode === CharCode.Tab) { - let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize; + const insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize; tabsCharDelta += insertSpacesCount - 1; // No need to render anything since tab is invisible dx += insertSpacesCount * charWidth; @@ -890,7 +890,7 @@ export class Minimap extends ViewPart { dx += charWidth; } else { // Render twice for a full width character - let count = strings.isFullWidthCharacter(charCode) ? 2 : 1; + const count = strings.isFullWidthCharacter(charCode) ? 2 : 1; for (let i = 0; i < count; i++) { if (renderMinimap === RenderMinimap.Large) { diff --git a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts index 2b25eb1575b..01a7a500105 100644 --- a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts +++ b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts @@ -90,7 +90,7 @@ export class ViewOverlayWidgets extends ViewPart { } public setWidgetPosition(widget: IOverlayWidget, preference: OverlayWidgetPositionPreference | null): boolean { - let widgetData = this._widgets[widget.getId()]; + const widgetData = this._widgets[widget.getId()]; if (widgetData.preference === preference) { return false; } @@ -102,7 +102,7 @@ export class ViewOverlayWidgets extends ViewPart { } public removeWidget(widget: IOverlayWidget): void { - let widgetId = widget.getId(); + const widgetId = widget.getId(); if (this._widgets.hasOwnProperty(widgetId)) { const widgetData = this._widgets[widgetId]; const domNode = widgetData.domNode.domNode; @@ -125,7 +125,7 @@ export class ViewOverlayWidgets extends ViewPart { domNode.setTop(0); domNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth); } else if (widgetData.preference === OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER) { - let widgetHeight = domNode.domNode.clientHeight; + const widgetHeight = domNode.domNode.clientHeight; domNode.setTop((this._editorHeight - widgetHeight - 2 * this._horizontalScrollbarHeight)); domNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth); } else if (widgetData.preference === OverlayWidgetPositionPreference.TOP_CENTER) { @@ -141,9 +141,9 @@ export class ViewOverlayWidgets extends ViewPart { public render(ctx: RestrictedRenderingContext): void { this._domNode.setWidth(this._editorWidth); - let keys = Object.keys(this._widgets); + const keys = Object.keys(this._widgets); for (let i = 0, len = keys.length; i < len; i++) { - let widgetId = keys[i]; + const widgetId = keys[i]; this._renderWidget(this._widgets[widgetId]); } } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index a8ee68ea1cc..2aaaac909bf 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -340,7 +340,7 @@ export class DecorationsOverviewRuler extends ViewPart { let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0; let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0; - let height = y2 - y1; + const height = y2 - y1; if (height < minDecorationHeight) { let yCenter = ((y1 + y2) / 2) | 0; if (yCenter < halfMinDecorationHeight) { diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index 748a3488d04..5de15bdf6c3 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -114,10 +114,10 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { const width = this._zoneManager.getCanvasWidth(); const height = this._zoneManager.getCanvasHeight(); - let colorZones = this._zoneManager.resolveColorZones(); - let id2Color = this._zoneManager.getId2Color(); + const colorZones = this._zoneManager.resolveColorZones(); + const id2Color = this._zoneManager.getId2Color(); - let ctx = this._domNode.domNode.getContext('2d')!; + const ctx = this._domNode.domNode.getContext('2d')!; ctx.clearRect(0, 0, width, height); if (colorZones.length > 0) { this._renderOneLane(ctx, colorZones, id2Color, width); diff --git a/src/vs/editor/browser/viewParts/rulers/rulers.ts b/src/vs/editor/browser/viewParts/rulers/rulers.ts index 5eca6700d6e..cdcd0e6d137 100644 --- a/src/vs/editor/browser/viewParts/rulers/rulers.ts +++ b/src/vs/editor/browser/viewParts/rulers/rulers.ts @@ -68,7 +68,7 @@ export class Rulers extends ViewPart { const rulerWidth = tabSize; let addCount = desiredCount - currentCount; while (addCount > 0) { - let node = createFastDomNode(document.createElement('div')); + const node = createFastDomNode(document.createElement('div')); node.setClassName('view-ruler'); node.setWidth(rulerWidth); this.domNode.appendChild(node); @@ -80,7 +80,7 @@ export class Rulers extends ViewPart { let removeCount = currentCount - desiredCount; while (removeCount > 0) { - let node = this._renderedRulers.pop()!; + const node = this._renderedRulers.pop()!; this.domNode.removeChild(node); removeCount--; } @@ -91,7 +91,7 @@ export class Rulers extends ViewPart { this._ensureRulersCount(); for (let i = 0, len = this._rulers.length; i < len; i++) { - let node = this._renderedRulers[i]; + const node = this._renderedRulers[i]; node.setHeight(Math.min(ctx.scrollHeight, 1000000)); node.setLeft(this._rulers[i] * this._typicalHalfwidthCharacterWidth); diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index 6d65eea7386..85219156191 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -38,7 +38,7 @@ export class ScrollDecorationViewPart extends ViewPart { } private _updateShouldShow(): boolean { - let newShouldShow = (this._useShadows && this._scrollTop > 0); + const newShouldShow = (this._useShadows && this._scrollTop > 0); if (this._shouldShow !== newShouldShow) { this._shouldShow = newShouldShow; return true; diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index 99d5696fede..f0edb18286d 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -143,7 +143,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { private _visibleRangesHaveGaps(linesVisibleRanges: LineVisibleRangesWithStyle[]): boolean { for (let i = 0, len = linesVisibleRanges.length; i < len; i++) { - let lineVisibleRanges = linesVisibleRanges[i]; + const lineVisibleRanges = linesVisibleRanges[i]; if (lineVisibleRanges.ranges.length > 1) { // There are two ranges on the same line @@ -161,7 +161,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (previousFrame && previousFrame.length > 0 && linesVisibleRanges.length > 0) { - let topLineNumber = linesVisibleRanges[0].lineNumber; + const topLineNumber = linesVisibleRanges[0].lineNumber; if (topLineNumber === viewport.startLineNumber) { for (let i = 0; !previousFrameTop && i < previousFrame.length; i++) { if (previousFrame[i].lineNumber === topLineNumber) { @@ -170,7 +170,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { } } - let bottomLineNumber = linesVisibleRanges[linesVisibleRanges.length - 1].lineNumber; + const bottomLineNumber = linesVisibleRanges[linesVisibleRanges.length - 1].lineNumber; if (bottomLineNumber === viewport.endLineNumber) { for (let i = previousFrame.length - 1; !previousFrameBottom && i >= 0; i--) { if (previousFrame[i].lineNumber === bottomLineNumber) { @@ -189,24 +189,24 @@ export class SelectionsOverlay extends DynamicViewOverlay { for (let i = 0, len = linesVisibleRanges.length; i < len; i++) { // We know for a fact that there is precisely one range on each line - let curLineRange = linesVisibleRanges[i].ranges[0]; - let curLeft = curLineRange.left; - let curRight = curLineRange.left + curLineRange.width; + const curLineRange = linesVisibleRanges[i].ranges[0]; + const curLeft = curLineRange.left; + const curRight = curLineRange.left + curLineRange.width; - let startStyle = { + const startStyle = { top: CornerStyle.EXTERN, bottom: CornerStyle.EXTERN }; - let endStyle = { + const endStyle = { top: CornerStyle.EXTERN, bottom: CornerStyle.EXTERN }; if (i > 0) { // Look above - let prevLeft = linesVisibleRanges[i - 1].ranges[0].left; - let prevRight = linesVisibleRanges[i - 1].ranges[0].left + linesVisibleRanges[i - 1].ranges[0].width; + const prevLeft = linesVisibleRanges[i - 1].ranges[0].left; + const prevRight = linesVisibleRanges[i - 1].ranges[0].left + linesVisibleRanges[i - 1].ranges[0].width; if (abs(curLeft - prevLeft) < epsilon) { startStyle.top = CornerStyle.FLAT; @@ -227,8 +227,8 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (i + 1 < len) { // Look below - let nextLeft = linesVisibleRanges[i + 1].ranges[0].left; - let nextRight = linesVisibleRanges[i + 1].ranges[0].left + linesVisibleRanges[i + 1].ranges[0].width; + const nextLeft = linesVisibleRanges[i + 1].ranges[0].left; + const nextRight = linesVisibleRanges[i + 1].ranges[0].left + linesVisibleRanges[i + 1].ranges[0].width; if (abs(curLeft - nextLeft) < epsilon) { startStyle.bottom = CornerStyle.FLAT; @@ -253,9 +253,9 @@ export class SelectionsOverlay extends DynamicViewOverlay { } private _getVisibleRangesWithStyle(selection: Range, ctx: RenderingContext, previousFrame: LineVisibleRangesWithStyle[] | null): LineVisibleRangesWithStyle[] { - let _linesVisibleRanges = ctx.linesVisibleRangesForRange(selection, true) || []; - let linesVisibleRanges = _linesVisibleRanges.map(toStyled); - let visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges); + const _linesVisibleRanges = ctx.linesVisibleRangesForRange(selection, true) || []; + const linesVisibleRanges = _linesVisibleRanges.map(toStyled); + const visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges); if (!isIEWithZoomingIssuesNearRoundedBorders && !visibleRangesHaveGaps && this._roundedSelection) { this._enrichVisibleRangesWithStyle(ctx.visibleRange, linesVisibleRanges, previousFrame); @@ -282,25 +282,25 @@ export class SelectionsOverlay extends DynamicViewOverlay { } private _actualRenderOneSelection(output2: string[], visibleStartLineNumber: number, hasMultipleSelections: boolean, visibleRanges: LineVisibleRangesWithStyle[]): void { - let visibleRangesHaveStyle = (visibleRanges.length > 0 && visibleRanges[0].ranges[0].startStyle); - let fullLineHeight = (this._lineHeight).toString(); - let reducedLineHeight = (this._lineHeight - 1).toString(); + const visibleRangesHaveStyle = (visibleRanges.length > 0 && visibleRanges[0].ranges[0].startStyle); + const fullLineHeight = (this._lineHeight).toString(); + const reducedLineHeight = (this._lineHeight - 1).toString(); - let firstLineNumber = (visibleRanges.length > 0 ? visibleRanges[0].lineNumber : 0); - let lastLineNumber = (visibleRanges.length > 0 ? visibleRanges[visibleRanges.length - 1].lineNumber : 0); + const firstLineNumber = (visibleRanges.length > 0 ? visibleRanges[0].lineNumber : 0); + const lastLineNumber = (visibleRanges.length > 0 ? visibleRanges[visibleRanges.length - 1].lineNumber : 0); for (let i = 0, len = visibleRanges.length; i < len; i++) { - let lineVisibleRanges = visibleRanges[i]; - let lineNumber = lineVisibleRanges.lineNumber; - let lineIndex = lineNumber - visibleStartLineNumber; + const lineVisibleRanges = visibleRanges[i]; + const lineNumber = lineVisibleRanges.lineNumber; + const lineIndex = lineNumber - visibleStartLineNumber; - let lineHeight = hasMultipleSelections ? (lineNumber === lastLineNumber || lineNumber === firstLineNumber ? reducedLineHeight : fullLineHeight) : fullLineHeight; - let top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0; + const lineHeight = hasMultipleSelections ? (lineNumber === lastLineNumber || lineNumber === firstLineNumber ? reducedLineHeight : fullLineHeight) : fullLineHeight; + const top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0; let lineOutput = ''; for (let j = 0, lenJ = lineVisibleRanges.ranges.length; j < lenJ; j++) { - let visibleRange = lineVisibleRanges.ranges[j]; + const visibleRange = lineVisibleRanges.ranges[j]; if (visibleRangesHaveStyle) { const startStyle = visibleRange.startStyle!; @@ -366,23 +366,23 @@ export class SelectionsOverlay extends DynamicViewOverlay { private _previousFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = []; public prepareRender(ctx: RenderingContext): void { - let output: string[] = []; - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let visibleEndLineNumber = ctx.visibleRange.endLineNumber; + const output: string[] = []; + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const visibleEndLineNumber = ctx.visibleRange.endLineNumber; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { - let lineIndex = lineNumber - visibleStartLineNumber; + const lineIndex = lineNumber - visibleStartLineNumber; output[lineIndex] = ''; } - let thisFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = []; + const thisFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = []; for (let i = 0, len = this._selections.length; i < len; i++) { - let selection = this._selections[i]; + const selection = this._selections[i]; if (selection.isEmpty()) { thisFrameVisibleRangesWithStyle[i] = null; continue; } - let visibleRangesWithStyle = this._getVisibleRangesWithStyle(selection, ctx, this._previousFrameVisibleRangesWithStyle[i]); + const visibleRangesWithStyle = this._getVisibleRangesWithStyle(selection, ctx, this._previousFrameVisibleRangesWithStyle[i]); thisFrameVisibleRangesWithStyle[i] = visibleRangesWithStyle; this._actualRenderOneSelection(output, visibleStartLineNumber, this._selections.length > 1, visibleRangesWithStyle); } @@ -395,7 +395,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (!this._renderResult) { return ''; } - let lineIndex = lineNumber - startLineNumber; + const lineIndex = lineNumber - startLineNumber; if (lineIndex < 0 || lineIndex >= this._renderResult.length) { return ''; } diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index 3d3450b6275..628bf4985ff 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -108,15 +108,15 @@ export class ViewCursors extends ViewPart { if (this._secondaryCursors.length < secondaryPositions.length) { // Create new cursors - let addCnt = secondaryPositions.length - this._secondaryCursors.length; + const addCnt = secondaryPositions.length - this._secondaryCursors.length; for (let i = 0; i < addCnt; i++) { - let newCursor = new ViewCursor(this._context); + const newCursor = new ViewCursor(this._context); this._domNode.domNode.insertBefore(newCursor.getDomNode().domNode, this._primaryCursor.getDomNode().domNode.nextSibling); this._secondaryCursors.push(newCursor); } } else if (this._secondaryCursors.length > secondaryPositions.length) { // Remove some cursors - let removeCnt = this._secondaryCursors.length - secondaryPositions.length; + const removeCnt = this._secondaryCursors.length - secondaryPositions.length; for (let i = 0; i < removeCnt; i++) { this._domNode.removeChild(this._secondaryCursors[0].getDomNode()); this._secondaryCursors.splice(0, 1); @@ -129,7 +129,7 @@ export class ViewCursors extends ViewPart { } public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { - let positions: Position[] = []; + const positions: Position[] = []; for (let i = 0, len = e.selections.length; i < len; i++) { positions[i] = e.selections[i].getPosition(); } @@ -169,7 +169,7 @@ export class ViewCursors extends ViewPart { return true; } public onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean { - let shouldRender = (position: Position) => { + const shouldRender = (position: Position) => { for (let i = 0, len = e.ranges.length; i < len; i++) { if (e.ranges[i].fromLineNumber <= position.lineNumber && position.lineNumber <= e.ranges[i].toLineNumber) { return true; @@ -209,11 +209,11 @@ export class ViewCursors extends ViewPart { this._startCursorBlinkAnimation.cancel(); this._cursorFlatBlinkInterval.cancel(); - let blinkingStyle = this._getCursorBlinking(); + const blinkingStyle = this._getCursorBlinking(); // hidden and solid are special as they involve no animations - let isHidden = (blinkingStyle === TextEditorCursorBlinkingStyle.Hidden); - let isSolid = (blinkingStyle === TextEditorCursorBlinkingStyle.Solid); + const isHidden = (blinkingStyle === TextEditorCursorBlinkingStyle.Hidden); + const isSolid = (blinkingStyle === TextEditorCursorBlinkingStyle.Solid); if (isHidden) { this._hide(); diff --git a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts index f148821b006..a51fbe5bf02 100644 --- a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts +++ b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts @@ -69,11 +69,11 @@ export class ViewZones extends ViewPart { private _recomputeWhitespacesProps(): boolean { let hadAChange = false; - let keys = Object.keys(this._zones); + const keys = Object.keys(this._zones); for (let i = 0, len = keys.length; i < len; i++) { - let id = keys[i]; - let zone = this._zones[id]; - let props = this._computeWhitespaceProps(zone.delegate); + const id = keys[i]; + const zone = this._zones[id]; + const props = this._computeWhitespaceProps(zone.delegate); if (this._context.viewLayout.changeWhitespace(parseInt(id, 10), props.afterViewLineNumber, props.heightInPx)) { this._safeCallOnComputedHeight(zone.delegate, props.heightInPx); hadAChange = true; @@ -150,7 +150,7 @@ export class ViewZones extends ViewPart { column: zone.afterColumn }); } else { - let validAfterLineNumber = this._context.model.validateModelPosition({ + const validAfterLineNumber = this._context.model.validateModelPosition({ lineNumber: zone.afterLineNumber, column: 1 }).lineNumber; @@ -174,8 +174,8 @@ export class ViewZones extends ViewPart { }); } - let viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(zoneAfterModelPosition); - let isVisible = this._context.model.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition); + const viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(zoneAfterModelPosition); + const isVisible = this._context.model.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition); return { afterViewLineNumber: viewPosition.lineNumber, heightInPx: (isVisible ? this._heightInPixels(zone) : 0), @@ -184,10 +184,10 @@ export class ViewZones extends ViewPart { } public addZone(zone: IViewZone): number { - let props = this._computeWhitespaceProps(zone); - let whitespaceId = this._context.viewLayout.addWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx); + const props = this._computeWhitespaceProps(zone); + const whitespaceId = this._context.viewLayout.addWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx); - let myZone: IMyViewZone = { + const myZone: IMyViewZone = { whitespaceId: whitespaceId, delegate: zone, isVisible: false, @@ -221,7 +221,7 @@ export class ViewZones extends ViewPart { public removeZone(id: number): boolean { if (this._zones.hasOwnProperty(id.toString())) { - let zone = this._zones[id.toString()]; + const zone = this._zones[id.toString()]; delete this._zones[id.toString()]; this._context.viewLayout.removeWhitespace(zone.whitespaceId); @@ -245,9 +245,9 @@ export class ViewZones extends ViewPart { public layoutZone(id: number): boolean { let changed = false; if (this._zones.hasOwnProperty(id.toString())) { - let zone = this._zones[id.toString()]; - let props = this._computeWhitespaceProps(zone.delegate); - // let newOrdinal = this._getZoneOrdinal(zone.delegate); + const zone = this._zones[id.toString()]; + const props = this._computeWhitespaceProps(zone.delegate); + // const newOrdinal = this._getZoneOrdinal(zone.delegate); changed = this._context.viewLayout.changeWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx) || changed; // TODO@Alex: change `newOrdinal` too @@ -261,7 +261,7 @@ export class ViewZones extends ViewPart { public shouldSuppressMouseDownOnViewZone(id: number): boolean { if (this._zones.hasOwnProperty(id.toString())) { - let zone = this._zones[id.toString()]; + const zone = this._zones[id.toString()]; return Boolean(zone.delegate.suppressMouseDown); } return false; @@ -310,7 +310,7 @@ export class ViewZones extends ViewPart { public render(ctx: RestrictedRenderingContext): void { const visibleWhitespaces = ctx.viewportData.whitespaceViewportData; - let visibleZones: { [id: string]: IViewWhitespaceViewportData; } = {}; + const visibleZones: { [id: string]: IViewWhitespaceViewportData; } = {}; let hasVisibleZone = false; for (let i = 0, len = visibleWhitespaces.length; i < len; i++) { @@ -318,10 +318,10 @@ export class ViewZones extends ViewPart { hasVisibleZone = true; } - let keys = Object.keys(this._zones); + const keys = Object.keys(this._zones); for (let i = 0, len = keys.length; i < len; i++) { - let id = keys[i]; - let zone = this._zones[id]; + const id = keys[i]; + const zone = this._zones[id]; let newTop = 0; let newHeight = 0; diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 5a0796a17d2..cef035a6e91 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -294,9 +294,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE contributions = EditorExtensionsRegistry.getEditorContributions(); } for (let i = 0, len = contributions.length; i < len; i++) { - let ctor = contributions[i]; + const ctor = contributions[i]; try { - let contribution = this._instantiationService.createInstance(ctor, this); + const contribution = this._instantiationService.createInstance(ctor, this); this._contributions[contribution.getId()] = contribution; } catch (err) { onUnexpectedError(err); @@ -339,9 +339,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._focusTracker.dispose(); - let keys = Object.keys(this._contributions); + const keys = Object.keys(this._contributions); for (let i = 0, len = keys.length; i < len; i++) { - let contributionId = keys[i]; + const contributionId = keys[i]; this._contributions[contributionId].dispose(); } @@ -374,7 +374,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return ''; } - let preserveBOM: boolean = (options && options.preserveBOM) ? true : false; + const preserveBOM: boolean = (options && options.preserveBOM) ? true : false; let eolPreference = EndOfLinePreference.TextDefined; if (options && options.lineEnding && options.lineEnding === '\n') { eolPreference = EndOfLinePreference.LF; @@ -409,10 +409,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return; } - let detachedModel = this._detachModel(); + const detachedModel = this._detachModel(); this._attachModel(model); - let e: editorCommon.IModelChangedEvent = { + const e: editorCommon.IModelChangedEvent = { oldModelUrl: detachedModel ? detachedModel.uri : null, newModelUrl: model ? model.uri : null }; @@ -426,7 +426,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._decorationTypeKeysToIds = {}; if (this._decorationTypeSubtypes) { for (let decorationType in this._decorationTypeSubtypes) { - let subTypes = this._decorationTypeSubtypes[decorationType]; + const subTypes = this._decorationTypeSubtypes[decorationType]; for (let subType in subTypes) { this._removeDecorationType(decorationType + '-' + subType); } @@ -450,11 +450,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } private static _getVerticalOffsetForPosition(modelData: ModelData, modelLineNumber: number, modelColumn: number): number { - let modelPosition = modelData.model.validatePosition({ + const modelPosition = modelData.model.validatePosition({ lineNumber: modelLineNumber, column: modelColumn }); - let viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition); + const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition); return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); } @@ -483,8 +483,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return rawPosition.column; } - let position = this._modelData.model.validatePosition(rawPosition); - let tabSize = this._modelData.model.getOptions().tabSize; + const position = this._modelData.model.validatePosition(rawPosition); + const tabSize = this._modelData.model.getOptions().tabSize; return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1; } @@ -608,8 +608,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE public setSelection(selection: ISelection): void; public setSelection(editorSelection: Selection): void; public setSelection(something: any): void { - let isSelection = Selection.isISelection(something); - let isRange = Range.isIRange(something); + const isSelection = Selection.isISelection(something); + const isRange = Range.isIRange(something); if (!isSelection && !isRange) { throw new Error('Invalid arguments'); @@ -619,7 +619,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._setSelectionImpl(something); } else if (isRange) { // act as if it was an IRange - let selection: ISelection = { + const selection: ISelection = { selectionStartLineNumber: something.startLineNumber, selectionStartColumn: something.startColumn, positionLineNumber: something.endLineNumber, @@ -633,7 +633,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE if (!this._modelData) { return; } - let selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn); + const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn); this._modelData.cursor.setSelections('api', [selection]); } @@ -825,7 +825,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } const codeEditorState = s as editorCommon.ICodeEditorViewState | null; if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) { - let cursorState = codeEditorState.cursorState; + const cursorState = codeEditorState.cursorState; if (Array.isArray(cursorState)) { this._modelData.cursor.restoreState(cursorState); } else { @@ -833,11 +833,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._modelData.cursor.restoreState([cursorState]); } - let contributionsState = codeEditorState.contributionsState || {}; - let keys = Object.keys(this._contributions); + const contributionsState = codeEditorState.contributionsState || {}; + const keys = Object.keys(this._contributions); for (let i = 0, len = keys.length; i < len; i++) { - let id = keys[i]; - let contribution = this._contributions[id]; + const id = keys[i]; + const contribution = this._contributions[id]; if (typeof contribution.restoreViewState === 'function') { contribution.restoreViewState(contributionsState[id]); } @@ -859,11 +859,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public getActions(): editorCommon.IEditorAction[] { - let result: editorCommon.IEditorAction[] = []; + const result: editorCommon.IEditorAction[] = []; - let keys = Object.keys(this._actions); + const keys = Object.keys(this._actions); for (let i = 0, len = keys.length; i < len; i++) { - let id = keys[i]; + const id = keys[i]; result.push(this._actions[id]); } @@ -1038,18 +1038,18 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE public setDecorations(decorationTypeKey: string, decorationOptions: editorCommon.IDecorationOptions[]): void { - let newDecorationsSubTypes: { [key: string]: boolean } = {}; - let oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {}; + const newDecorationsSubTypes: { [key: string]: boolean } = {}; + const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {}; this._decorationTypeSubtypes[decorationTypeKey] = newDecorationsSubTypes; - let newModelDecorations: IModelDeltaDecoration[] = []; + const newModelDecorations: IModelDeltaDecoration[] = []; for (let decorationOption of decorationOptions) { let typeKey = decorationTypeKey; if (decorationOption.renderOptions) { // identify custom reder options by a hash code over all keys and values // For custom render options register a decoration type if necessary - let subType = hash(decorationOption.renderOptions).toString(16); + const subType = hash(decorationOption.renderOptions).toString(16); // The fact that `decorationTypeKey` appears in the typeKey has no influence // it is just a mechanism to get predictable and unique keys (repeatable for the same options and unique across clients) typeKey = decorationTypeKey + '-' + subType; @@ -1059,7 +1059,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } newDecorationsSubTypes[subType] = true; } - let opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage); + const opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage); if (decorationOption.hoverMessage) { opts.hoverMessage = decorationOption.hoverMessage; } @@ -1074,33 +1074,33 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } // update all decorations - let oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || []; + const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || []; this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations); } public setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void { // remove decoration sub types that are no longer used, deregister decoration type if necessary - let oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {}; + const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {}; for (let subType in oldDecorationsSubTypes) { this._removeDecorationType(decorationTypeKey + '-' + subType); } this._decorationTypeSubtypes[decorationTypeKey] = {}; const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false)); - let newModelDecorations: IModelDeltaDecoration[] = new Array(ranges.length); + const newModelDecorations: IModelDeltaDecoration[] = new Array(ranges.length); for (let i = 0, len = ranges.length; i < len; i++) { newModelDecorations[i] = { range: ranges[i], options: opts }; } // update all decorations - let oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || []; + const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || []; this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations); } public removeDecorations(decorationTypeKey: string): void { // remove decorations for type and sub type - let oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey]; + const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey]; if (oldDecorationsIds) { this.deltaDecorations(oldDecorationsIds, []); } @@ -1161,7 +1161,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public addContentWidget(widget: editorBrowser.IContentWidget): void { - let widgetData: IContentWidgetData = { + const widgetData: IContentWidgetData = { widget: widget, position: widget.getPosition() }; @@ -1178,9 +1178,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public layoutContentWidget(widget: editorBrowser.IContentWidget): void { - let widgetId = widget.getId(); + const widgetId = widget.getId(); if (this._contentWidgets.hasOwnProperty(widgetId)) { - let widgetData = this._contentWidgets[widgetId]; + const widgetData = this._contentWidgets[widgetId]; widgetData.position = widget.getPosition(); if (this._modelData && this._modelData.hasRealView) { this._modelData.view.layoutContentWidget(widgetData); @@ -1189,9 +1189,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public removeContentWidget(widget: editorBrowser.IContentWidget): void { - let widgetId = widget.getId(); + const widgetId = widget.getId(); if (this._contentWidgets.hasOwnProperty(widgetId)) { - let widgetData = this._contentWidgets[widgetId]; + const widgetData = this._contentWidgets[widgetId]; delete this._contentWidgets[widgetId]; if (this._modelData && this._modelData.hasRealView) { this._modelData.view.removeContentWidget(widgetData); @@ -1200,7 +1200,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public addOverlayWidget(widget: editorBrowser.IOverlayWidget): void { - let widgetData: IOverlayWidgetData = { + const widgetData: IOverlayWidgetData = { widget: widget, position: widget.getPosition() }; @@ -1217,9 +1217,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void { - let widgetId = widget.getId(); + const widgetId = widget.getId(); if (this._overlayWidgets.hasOwnProperty(widgetId)) { - let widgetData = this._overlayWidgets[widgetId]; + const widgetData = this._overlayWidgets[widgetId]; widgetData.position = widget.getPosition(); if (this._modelData && this._modelData.hasRealView) { this._modelData.view.layoutOverlayWidget(widgetData); @@ -1228,9 +1228,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void { - let widgetId = widget.getId(); + const widgetId = widget.getId(); if (this._overlayWidgets.hasOwnProperty(widgetId)) { - let widgetData = this._overlayWidgets[widgetId]; + const widgetData = this._overlayWidgets[widgetId]; delete this._overlayWidgets[widgetId]; if (this._modelData && this._modelData.hasRealView) { this._modelData.view.removeOverlayWidget(widgetData); @@ -1242,7 +1242,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE if (!this._modelData || !this._modelData.hasRealView) { return; } - let hasChanges = this._modelData.view.change(callback); + const hasChanges = this._modelData.view.change(callback); if (hasChanges) { this._onDidChangeViewZones.fire(); } @@ -1260,11 +1260,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return null; } - let position = this._modelData.model.validatePosition(rawPosition); - let layoutInfo = this._configuration.editor.layoutInfo; + const position = this._modelData.model.validatePosition(rawPosition); + const layoutInfo = this._configuration.editor.layoutInfo; - let top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop(); - let left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft(); + const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop(); + const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft(); return { top: top, @@ -1329,7 +1329,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE })); listenersToRemove.push(cursor.onDidChange((e: CursorStateChangedEvent) => { - let positions: Position[] = []; + const positions: Position[] = []; for (let i = 0, len = e.selections.length; i < len; i++) { positions[i] = e.selections[i].getPosition(); } @@ -1357,13 +1357,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE let keys = Object.keys(this._contentWidgets); for (let i = 0, len = keys.length; i < len; i++) { - let widgetId = keys[i]; + const widgetId = keys[i]; view.addContentWidget(this._contentWidgets[widgetId]); } keys = Object.keys(this._overlayWidgets); for (let i = 0, len = keys.length; i < len; i++) { - let widgetId = keys[i]; + const widgetId = keys[i]; view.addOverlayWidget(this._overlayWidgets[widgetId]); } @@ -1534,7 +1534,7 @@ export class BooleanEventEmitter extends Disposable { } public setValue(_value: boolean) { - let value = (_value ? BooleanEventValue.True : BooleanEventValue.False); + const value = (_value ? BooleanEventValue.True : BooleanEventValue.False); if (this._value === value) { return; } @@ -1595,14 +1595,14 @@ class EditorContextKeysManager extends Disposable { } private _updateFromConfig(): void { - let config = this._editor.getConfiguration(); + const config = this._editor.getConfiguration(); this._editorTabMovesFocus.set(config.tabFocusMode); this._editorReadonly.set(config.readOnly); } private _updateFromSelection(): void { - let selections = this._editor.getSelections(); + const selections = this._editor.getSelections(); if (!selections) { this._hasMultipleSelections.reset(); this._hasNonEmptySelection.reset(); diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index a3dfb3bc268..a484df5b06e 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -287,7 +287,7 @@ export const enum CompletionItemKind { /** * @internal */ -export let completionKindToCssClass = (function () { +export const completionKindToCssClass = (function () { let data = Object.create(null); data[CompletionItemKind.Method] = 'method'; data[CompletionItemKind.Function] = 'function'; From 013501950e78b9dde5c2e6ec3f2ddfb9201156b7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 6 Mar 2019 14:32:49 -0800 Subject: [PATCH 172/172] Auto marking private fields readonly in vs/editor Readonly helps with type guards and code comprehension --- src/vs/editor/browser/config/configuration.ts | 4 +- .../browser/config/elementSizeObserver.ts | 4 +- .../editor/browser/controller/mouseHandler.ts | 4 +- .../editor/browser/controller/mouseTarget.ts | 4 +- .../browser/controller/pointerHandler.ts | 2 +- src/vs/editor/browser/editorDom.ts | 6 +- src/vs/editor/browser/editorExtensions.ts | 8 +-- .../services/abstractCodeEditorService.ts | 6 +- .../browser/services/codeEditorServiceImpl.ts | 16 ++--- src/vs/editor/browser/view/viewImpl.ts | 6 +- .../editor/browser/view/viewOutgoingEvents.ts | 2 +- src/vs/editor/browser/view/viewOverlays.ts | 4 +- .../contentWidgets/contentWidgets.ts | 4 +- .../currentLineHighlight.ts | 2 +- .../currentLineMarginHighlight.ts | 2 +- .../viewParts/decorations/decorations.ts | 2 +- .../editorScrollbar/editorScrollbar.ts | 4 +- .../viewParts/glyphMargin/glyphMargin.ts | 2 +- .../viewParts/indentGuides/indentGuides.ts | 2 +- .../viewParts/lineNumbers/lineNumbers.ts | 2 +- .../browser/viewParts/lines/viewLine.ts | 2 +- .../browser/viewParts/lines/viewLines.ts | 4 +- .../linesDecorations/linesDecorations.ts | 2 +- .../editor/browser/viewParts/margin/margin.ts | 2 +- .../marginDecorations/marginDecorations.ts | 2 +- .../overlayWidgets/overlayWidgets.ts | 2 +- .../viewParts/overviewRuler/overviewRuler.ts | 6 +- .../editor/browser/viewParts/rulers/rulers.ts | 2 +- .../scrollDecoration/scrollDecoration.ts | 2 +- .../viewParts/selections/selections.ts | 2 +- .../viewParts/viewCursors/viewCursors.ts | 10 +-- .../editor/browser/widget/codeEditorWidget.ts | 62 +++++++++---------- .../editor/browser/widget/diffEditorWidget.ts | 36 +++++------ .../widget/embeddedCodeEditorWidget.ts | 8 +-- .../editor/common/commands/replaceCommand.ts | 6 +- src/vs/editor/common/commands/shiftCommand.ts | 4 +- .../commands/surroundSelectionCommand.ts | 6 +- .../commands/trimTrailingWhitespaceCommand.ts | 4 +- .../editor/common/core/characterClassifier.ts | 2 +- src/vs/editor/common/core/uint.ts | 2 +- src/vs/editor/common/model/editStack.ts | 2 +- .../pieceTreeTextBuffer/pieceTreeBase.ts | 8 +-- .../pieceTreeTextBuffer.ts | 4 +- .../pieceTreeTextBufferBuilder.ts | 4 +- src/vs/editor/common/model/textModel.ts | 8 +-- src/vs/editor/common/model/textModelSearch.ts | 4 +- src/vs/editor/common/model/textModelTokens.ts | 2 +- src/vs/editor/common/modes/abstractMode.ts | 2 +- .../modes/languageConfigurationRegistry.ts | 2 +- .../common/modes/languageFeatureRegistry.ts | 2 +- src/vs/editor/common/modes/linkComputer.ts | 4 +- src/vs/editor/common/modes/modesRegistry.ts | 2 +- .../modes/supports/inplaceReplaceSupport.ts | 2 +- .../common/modes/supports/tokenization.ts | 4 +- .../common/modes/tokenizationRegistry.ts | 4 +- .../common/services/editorSimpleWorker.ts | 2 +- .../services/editorWorkerServiceImpl.ts | 14 ++--- .../common/services/languagesRegistry.ts | 4 +- .../common/services/modelServiceImpl.ts | 8 +-- src/vs/editor/common/services/webWorker.ts | 2 +- .../editor/common/view/overviewZoneManager.ts | 6 +- .../editor/common/view/viewEventDispatcher.ts | 4 +- .../common/viewLayout/lineDecorations.ts | 4 +- .../editor/common/viewLayout/linesLayout.ts | 2 +- .../common/viewLayout/whitespaceComputer.ts | 14 ++--- .../characterHardWrappingLineMapper.ts | 6 +- .../common/viewModel/prefixSumComputer.ts | 2 +- .../common/viewModel/splitLinesCollection.ts | 12 ++-- .../bracketMatching/bracketMatching.ts | 2 +- .../caretOperations/caretOperations.ts | 2 +- .../caretOperations/moveCaretCommand.ts | 4 +- src/vs/editor/contrib/clipboard/clipboard.ts | 2 +- .../contrib/codeAction/codeActionCommands.ts | 10 +-- .../contrib/codeAction/codeActionModel.ts | 4 +- .../contrib/codelens/codelensController.ts | 2 +- .../editor/contrib/codelens/codelensWidget.ts | 8 +-- .../contrib/colorPicker/colorDetector.ts | 4 +- .../contrib/colorPicker/colorPickerWidget.ts | 26 ++++---- .../contrib/comment/blockCommentCommand.ts | 2 +- src/vs/editor/contrib/comment/comment.ts | 2 +- .../contrib/comment/lineCommentCommand.ts | 6 +- .../editor/contrib/contextmenu/contextmenu.ts | 2 +- src/vs/editor/contrib/dnd/dnd.ts | 2 +- .../editor/contrib/dnd/dragAndDropCommand.ts | 6 +- src/vs/editor/contrib/find/findController.ts | 6 +- src/vs/editor/contrib/find/findDecorations.ts | 2 +- src/vs/editor/contrib/find/findModel.ts | 10 +-- .../editor/contrib/find/findOptionsWidget.ts | 14 ++--- src/vs/editor/contrib/find/findWidget.ts | 14 ++--- .../editor/contrib/find/replaceAllCommand.ts | 6 +- .../editor/contrib/find/simpleFindWidget.ts | 12 ++-- src/vs/editor/contrib/folding/folding.ts | 4 +- .../contrib/folding/foldingDecorations.ts | 2 +- src/vs/editor/contrib/folding/foldingModel.ts | 4 +- .../editor/contrib/folding/foldingRanges.ts | 10 +-- .../contrib/folding/hiddenRangeModel.ts | 2 +- .../contrib/folding/indentRangeProvider.ts | 10 +-- .../folding/intializingRangeProvider.ts | 2 +- .../contrib/folding/syntaxRangeProvider.ts | 14 ++--- .../goToDefinition/goToDefinitionMouse.ts | 2 +- src/vs/editor/contrib/gotoError/gotoError.ts | 10 +-- .../contrib/gotoError/gotoErrorWidget.ts | 4 +- src/vs/editor/contrib/hover/hover.ts | 2 +- src/vs/editor/contrib/hover/hoverOperation.ts | 14 ++--- src/vs/editor/contrib/hover/hoverWidgets.ts | 12 ++-- .../editor/contrib/hover/modesContentHover.ts | 8 +-- .../editor/contrib/hover/modesGlyphHover.ts | 8 +-- .../inPlaceReplace/inPlaceReplaceCommand.ts | 6 +- .../editor/contrib/indentation/indentation.ts | 12 ++-- .../linesOperations/copyLinesCommand.ts | 4 +- .../linesOperations/linesOperations.ts | 6 +- .../linesOperations/moveLinesCommand.ts | 6 +- .../linesOperations/sortLinesCommand.ts | 4 +- src/vs/editor/contrib/links/getLinks.ts | 2 +- src/vs/editor/contrib/links/links.ts | 8 +-- .../contrib/message/messageController.ts | 10 +-- .../editor/contrib/multicursor/multicursor.ts | 4 +- .../parameterHints/parameterHintsModel.ts | 4 +- .../parameterHints/parameterHintsWidget.ts | 2 +- .../referenceSearch/referencesController.ts | 6 +- .../referenceSearch/referencesModel.ts | 2 +- .../editor/contrib/suggest/suggestWidget.ts | 16 ++--- .../wordHighlighter/wordHighlighter.ts | 10 +-- .../editor/contrib/zoneWidget/zoneWidget.ts | 8 +-- .../accessibilityHelp/accessibilityHelp.ts | 12 ++-- .../iPadShowKeyboard/iPadShowKeyboard.ts | 6 +- .../browser/inspectTokens/inspectTokens.ts | 14 ++--- .../browser/quickOpen/editorQuickOpen.ts | 4 +- .../standalone/browser/quickOpen/gotoLine.ts | 6 +- .../browser/quickOpen/quickCommand.ts | 8 +-- .../quickOpen/quickOpenEditorWidget.ts | 4 +- .../browser/quickOpen/quickOutline.ts | 12 ++-- .../standalone/browser/simpleServices.ts | 10 +-- .../browser/standaloneCodeEditor.ts | 6 +- .../standalone/browser/standaloneServices.ts | 8 +-- .../browser/standaloneThemeServiceImpl.ts | 10 +-- .../standalone/common/monarch/monarchLexer.ts | 8 +-- .../test/browser/controller/imeTester.ts | 2 +- src/vs/editor/test/common/mocks/mockMode.ts | 2 +- 139 files changed, 432 insertions(+), 432 deletions(-) diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 1a61fdfeb33..c7fa9fb94c6 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -19,8 +19,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib class CSSBasedConfigurationCache { - private _keys: { [key: string]: BareFontInfo; }; - private _values: { [key: string]: FontInfo; }; + private readonly _keys: { [key: string]: BareFontInfo; }; + private readonly _values: { [key: string]: FontInfo; }; constructor() { this._keys = Object.create(null); diff --git a/src/vs/editor/browser/config/elementSizeObserver.ts b/src/vs/editor/browser/config/elementSizeObserver.ts index 77a74232b60..325741e7293 100644 --- a/src/vs/editor/browser/config/elementSizeObserver.ts +++ b/src/vs/editor/browser/config/elementSizeObserver.ts @@ -8,9 +8,9 @@ import { IDimension } from 'vs/editor/common/editorCommon'; export class ElementSizeObserver extends Disposable { - private referenceDomElement: HTMLElement | null; + private readonly referenceDomElement: HTMLElement | null; private measureReferenceDomElementToken: any; - private changeCallback: () => void; + private readonly changeCallback: () => void; private width: number; private height: number; diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index 2c70cab83ac..b3b447201c6 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -69,9 +69,9 @@ export class MouseHandler extends ViewEventHandler { protected viewController: ViewController; protected viewHelper: IPointerHandlerHelper; protected mouseTargetFactory: MouseTargetFactory; - private _asyncFocus: RunOnceScheduler; + private readonly _asyncFocus: RunOnceScheduler; - private _mouseDownOperation: MouseDownOperation; + private readonly _mouseDownOperation: MouseDownOperation; private lastMouseLeaveTime: number; constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) { diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 70d6b935a2b..8d69b3dffbf 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -430,8 +430,8 @@ function createEmptyContentDataInLines(horizontalDistanceToText: number): IEmpty export class MouseTargetFactory { - private _context: ViewContext; - private _viewHelper: IPointerHandlerHelper; + private readonly _context: ViewContext; + private readonly _viewHelper: IPointerHandlerHelper; constructor(context: ViewContext, viewHelper: IPointerHandlerHelper) { this._context = context; diff --git a/src/vs/editor/browser/controller/pointerHandler.ts b/src/vs/editor/browser/controller/pointerHandler.ts index 57cd5cc879d..f744847b48f 100644 --- a/src/vs/editor/browser/controller/pointerHandler.ts +++ b/src/vs/editor/browser/controller/pointerHandler.ts @@ -220,7 +220,7 @@ class TouchHandler extends MouseHandler { } export class PointerHandler implements IDisposable { - private handler: MouseHandler; + private readonly handler: MouseHandler; constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) { if (window.navigator.msPointerEnabled) { diff --git a/src/vs/editor/browser/editorDom.ts b/src/vs/editor/browser/editorDom.ts index 23a905a4aeb..92357091f08 100644 --- a/src/vs/editor/browser/editorDom.ts +++ b/src/vs/editor/browser/editorDom.ts @@ -89,7 +89,7 @@ export interface EditorMouseEventMerger { export class EditorMouseEventFactory { - private _editorViewDomNode: HTMLElement; + private readonly _editorViewDomNode: HTMLElement; constructor(editorViewDomNode: HTMLElement) { this._editorViewDomNode = editorViewDomNode; @@ -133,8 +133,8 @@ export class EditorMouseEventFactory { export class GlobalEditorMouseMoveMonitor extends Disposable { - private _editorViewDomNode: HTMLElement; - private _globalMouseMoveMonitor: GlobalMouseMoveMonitor; + private readonly _editorViewDomNode: HTMLElement; + private readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor; private _keydownListener: IDisposable | null; constructor(editorViewDomNode: HTMLElement) { diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index 742095a1ad1..7406de01ffb 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -127,7 +127,7 @@ export abstract class EditorCommand extends Command { */ public static bindToContribution(controllerGetter: (editor: ICodeEditor) => T): EditorControllerCommand { return class EditorControllerCommandImpl extends EditorCommand { - private _callback: (controller: T, args: any) => void; + private readonly _callback: (controller: T, args: any) => void; constructor(opts: IContributionCommandOptions) { super(opts); @@ -320,9 +320,9 @@ class EditorContributionRegistry { public static readonly INSTANCE = new EditorContributionRegistry(); - private editorContributions: IEditorContributionCtor[]; - private editorActions: EditorAction[]; - private editorCommands: { [commandId: string]: EditorCommand; }; + private readonly editorContributions: IEditorContributionCtor[]; + private readonly editorActions: EditorAction[]; + private readonly editorCommands: { [commandId: string]: EditorCommand; }; constructor() { this.editorContributions = []; diff --git a/src/vs/editor/browser/services/abstractCodeEditorService.ts b/src/vs/editor/browser/services/abstractCodeEditorService.ts index f6a20ee4e11..c4a4be40d46 100644 --- a/src/vs/editor/browser/services/abstractCodeEditorService.ts +++ b/src/vs/editor/browser/services/abstractCodeEditorService.ts @@ -31,8 +31,8 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC public readonly onDidChangeTransientModelProperty: Event = this._onDidChangeTransientModelProperty.event; - private _codeEditors: { [editorId: string]: ICodeEditor; }; - private _diffEditors: { [editorId: string]: IDiffEditor; }; + private readonly _codeEditors: { [editorId: string]: ICodeEditor; }; + private readonly _diffEditors: { [editorId: string]: IDiffEditor; }; constructor() { super(); @@ -93,7 +93,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC abstract removeDecorationType(key: string): void; abstract resolveDecorationOptions(decorationTypeKey: string | undefined, writable: boolean): IModelDecorationOptions; - private _transientWatchers: { [uri: string]: ModelTransientSettingWatcher; } = {}; + private readonly _transientWatchers: { [uri: string]: ModelTransientSettingWatcher; } = {}; public setTransientModelProperty(model: ITextModel, key: string, value: any): void { const uri = model.uri.toString(); diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index f99a7f87b2e..7ad0bcc4078 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -16,9 +16,9 @@ import { ITheme, IThemeService, ThemeColor } from 'vs/platform/theme/common/them export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { - private _styleSheet: HTMLStyleElement; - private _decorationOptionProviders: { [key: string]: IModelDecorationOptionsProvider }; - private _themeService: IThemeService; + private readonly _styleSheet: HTMLStyleElement; + private readonly _decorationOptionProviders: { [key: string]: IModelDecorationOptionsProvider }; + private readonly _themeService: IThemeService; constructor(@IThemeService themeService: IThemeService, styleSheet = dom.createStyleSheet()) { super(); @@ -79,7 +79,7 @@ class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvide public refCount: number; - private _parentTypeKey: string | undefined; + private readonly _parentTypeKey: string | undefined; private _beforeContentRules: DecorationCSSRules | null; private _afterContentRules: DecorationCSSRules | null; @@ -245,13 +245,13 @@ const _CSS_MAP: { [prop: string]: string; } = { class DecorationCSSRules { private _theme: ITheme; - private _className: string; - private _unThemedSelector: string; + private readonly _className: string; + private readonly _unThemedSelector: string; private _hasContent: boolean; private _hasLetterSpacing: boolean; - private _ruleType: ModelDecorationCSSRuleType; + private readonly _ruleType: ModelDecorationCSSRuleType; private _themeListener: IDisposable | null; - private _providerArgs: ProviderArguments; + private readonly _providerArgs: ProviderArguments; private _usesThemeColors: boolean; public constructor(ruleType: ModelDecorationCSSRuleType, providerArgs: ProviderArguments, themeService: IThemeService) { diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 256fa4f67c1..b6240b274a1 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -63,11 +63,11 @@ const invalidFunc = () => { throw new Error(`Invalid change accessor`); }; export class View extends ViewEventHandler { - private eventDispatcher: ViewEventDispatcher; + private readonly eventDispatcher: ViewEventDispatcher; private _scrollbar: EditorScrollbar; - private _context: ViewContext; - private _cursor: Cursor; + private readonly _context: ViewContext; + private readonly _cursor: Cursor; // The view lines private viewLines: ViewLines; diff --git a/src/vs/editor/browser/view/viewOutgoingEvents.ts b/src/vs/editor/browser/view/viewOutgoingEvents.ts index 9c8c23470ad..ca110d888c8 100644 --- a/src/vs/editor/browser/view/viewOutgoingEvents.ts +++ b/src/vs/editor/browser/view/viewOutgoingEvents.ts @@ -32,7 +32,7 @@ export class ViewOutgoingEvents extends Disposable { public onMouseDrag: EventCallback | null = null; public onMouseDrop: EventCallback | null = null; - private _viewModel: IViewModel; + private readonly _viewModel: IViewModel; constructor(viewModel: IViewModel) { super(); diff --git a/src/vs/editor/browser/view/viewOverlays.ts b/src/vs/editor/browser/view/viewOverlays.ts index 82d89966fdb..bc75a6b4cef 100644 --- a/src/vs/editor/browser/view/viewOverlays.ts +++ b/src/vs/editor/browser/view/viewOverlays.ts @@ -139,8 +139,8 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost | null; private _renderedContent: string | null; private _lineHeight: number; diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index f5b27f92188..f82b04c8475 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -29,7 +29,7 @@ class Coordinate { export class ViewContentWidgets extends ViewPart { - private _viewDomNode: FastDomNode; + private readonly _viewDomNode: FastDomNode; private _widgets: { [key: string]: Widget; }; public domNode: FastDomNode; @@ -180,7 +180,7 @@ class Widget { public readonly allowEditorOverflow: boolean; public readonly suppressMouseDown: boolean; - private _fixedOverflowWidgets: boolean; + private readonly _fixedOverflowWidgets: boolean; private _contentWidth: number; private _contentLeft: number; private _lineHeight: number; diff --git a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts index 5a49e8d3070..d707bbad7c5 100644 --- a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts +++ b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts @@ -12,7 +12,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; export class CurrentLineHighlightOverlay extends DynamicViewOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _renderLineHighlight: 'none' | 'gutter' | 'line' | 'all'; private _selectionIsEmpty: boolean; diff --git a/src/vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight.ts b/src/vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight.ts index b3054d0408a..55145073655 100644 --- a/src/vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight.ts +++ b/src/vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight.ts @@ -12,7 +12,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; export class CurrentLineMarginHighlightOverlay extends DynamicViewOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _renderLineHighlight: 'none' | 'gutter' | 'line' | 'all'; private _selectionIsEmpty: boolean; diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index a6ecaf390eb..0716cc3b4e1 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -13,7 +13,7 @@ import { ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel'; export class DecorationsOverlay extends DynamicViewOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _typicalHalfwidthCharacterWidth: number; private _renderResult: string[] | null; diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts index add801b30ee..d9b8c4dfd8f 100644 --- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts +++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts @@ -17,8 +17,8 @@ import { getThemeTypeSelector } from 'vs/platform/theme/common/themeService'; export class EditorScrollbar extends ViewPart { - private scrollbar: SmoothScrollableElement; - private scrollbarDomNode: FastDomNode; + private readonly scrollbar: SmoothScrollableElement; + private readonly scrollbarDomNode: FastDomNode; constructor( context: ViewContext, diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index baf374971fb..60c18790d0c 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -74,7 +74,7 @@ export abstract class DedupOverlay extends DynamicViewOverlay { export class GlyphMarginOverlay extends DedupOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _glyphMargin: boolean; private _glyphMarginLeft: number; diff --git a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts index bc1373afe48..323a8097cec 100644 --- a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts +++ b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts @@ -14,7 +14,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic export class IndentGuidesOverlay extends DynamicViewOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _primaryLineNumber: number; private _lineHeight: number; private _spaceWidth: number; diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts index 79404907337..8ccd25f7453 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts @@ -18,7 +18,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { public static readonly CLASS_NAME = 'line-numbers'; - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _renderLineNumbers: RenderLineNumbersType; diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index ab8934477c9..e2397249709 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -398,7 +398,7 @@ class RenderedViewLine implements IRenderedViewLine { /** * This is a map that is used only when the line is guaranteed to have no RTL text. */ - private _pixelOffsetCache: Int32Array | null; + private readonly _pixelOffsetCache: Int32Array | null; constructor(domNode: FastDomNode, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) { this.domNode = domNode; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 136d50501ab..ba4d49c639a 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -76,10 +76,10 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, // --- width private _maxLineWidth: number; - private _asyncUpdateLineWidths: RunOnceScheduler; + private readonly _asyncUpdateLineWidths: RunOnceScheduler; private _horizontalRevealRequest: HorizontalRevealRequest | null; - private _lastRenderedData: LastRenderedData; + private readonly _lastRenderedData: LastRenderedData; constructor(context: ViewContext, linesContent: FastDomNode) { super(context); diff --git a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts index 1dec064a1ba..fe764290bad 100644 --- a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts +++ b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts @@ -11,7 +11,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; export class LinesDecorationsOverlay extends DedupOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _decorationsLeft: number; private _decorationsWidth: number; diff --git a/src/vs/editor/browser/viewParts/margin/margin.ts b/src/vs/editor/browser/viewParts/margin/margin.ts index 0cb8b7bcd98..eda44ab11d6 100644 --- a/src/vs/editor/browser/viewParts/margin/margin.ts +++ b/src/vs/editor/browser/viewParts/margin/margin.ts @@ -14,7 +14,7 @@ export class Margin extends ViewPart { public static readonly CLASS_NAME = 'glyph-margin'; public static readonly OUTER_CLASS_NAME = 'margin'; - private _domNode: FastDomNode; + private readonly _domNode: FastDomNode; private _canUseLayerHinting: boolean; private _contentLeft: number; private _glyphMarginLeft: number; diff --git a/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts b/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts index 3e757cd2a8e..7f5d18d8621 100644 --- a/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts +++ b/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts @@ -10,7 +10,7 @@ import { ViewContext } from 'vs/editor/common/view/viewContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; export class MarginViewLineDecorationsOverlay extends DedupOverlay { - private _context: ViewContext; + private readonly _context: ViewContext; private _renderResult: string[] | null; constructor(context: ViewContext) { diff --git a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts index 01a7a500105..87a35ca24f2 100644 --- a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts +++ b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts @@ -24,7 +24,7 @@ interface IWidgetMap { export class ViewOverlayWidgets extends ViewPart { private _widgets: IWidgetMap; - private _domNode: FastDomNode; + private readonly _domNode: FastDomNode; private _verticalScrollbarWidth: number; private _minimapWidth: number; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index 5de15bdf6c3..4b164f01c6b 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -13,9 +13,9 @@ import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { - private _context: ViewContext; - private _domNode: FastDomNode; - private _zoneManager: OverviewZoneManager; + private readonly _context: ViewContext; + private readonly _domNode: FastDomNode; + private readonly _zoneManager: OverviewZoneManager; constructor(context: ViewContext, cssClassName: string) { super(); diff --git a/src/vs/editor/browser/viewParts/rulers/rulers.ts b/src/vs/editor/browser/viewParts/rulers/rulers.ts index cdcd0e6d137..7d4d402d24e 100644 --- a/src/vs/editor/browser/viewParts/rulers/rulers.ts +++ b/src/vs/editor/browser/viewParts/rulers/rulers.ts @@ -15,7 +15,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic export class Rulers extends ViewPart { public domNode: FastDomNode; - private _renderedRulers: FastDomNode[]; + private readonly _renderedRulers: FastDomNode[]; private _rulers: number[]; private _typicalHalfwidthCharacterWidth: number; diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index 85219156191..2ae336437e4 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -14,7 +14,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic export class ScrollDecorationViewPart extends ViewPart { - private _domNode: FastDomNode; + private readonly _domNode: FastDomNode; private _scrollTop: number; private _width: number; private _shouldShow: boolean; diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index f0edb18286d..3ee089a3d94 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -73,7 +73,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { private static readonly ROUNDED_PIECE_WIDTH = 10; - private _context: ViewContext; + private readonly _context: ViewContext; private _lineHeight: number; private _roundedSelection: boolean; private _typicalHalfwidthCharacterWidth: number; diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index 628bf4985ff..982b021bd1a 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -28,16 +28,16 @@ export class ViewCursors extends ViewPart { private _isVisible: boolean; - private _domNode: FastDomNode; + private readonly _domNode: FastDomNode; - private _startCursorBlinkAnimation: TimeoutTimer; - private _cursorFlatBlinkInterval: IntervalTimer; + private readonly _startCursorBlinkAnimation: TimeoutTimer; + private readonly _cursorFlatBlinkInterval: IntervalTimer; private _blinkingEnabled: boolean; private _editorHasFocus: boolean; - private _primaryCursor: ViewCursor; - private _secondaryCursors: ViewCursor[]; + private readonly _primaryCursor: ViewCursor; + private readonly _secondaryCursors: ViewCursor[]; private _renderData: IViewCursorRenderData[]; constructor(context: ViewContext) { diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index cef035a6e91..16263681984 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -141,11 +141,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE private readonly _onDidLayoutChange: Emitter = this._register(new Emitter()); public readonly onDidLayoutChange: Event = this._onDidLayoutChange.event; - private _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); + private readonly _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); public readonly onDidFocusEditorText: Event = this._editorTextFocus.onDidChangeToTrue; public readonly onDidBlurEditorText: Event = this._editorTextFocus.onDidChangeToFalse; - private _editorWidgetFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); + private readonly _editorWidgetFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); public readonly onDidFocusEditorWidget: Event = this._editorWidgetFocus.onDidChangeToTrue; public readonly onDidBlurEditorWidget: Event = this._editorWidgetFocus.onDidChangeToFalse; @@ -1549,16 +1549,16 @@ export class BooleanEventEmitter extends Disposable { class EditorContextKeysManager extends Disposable { - private _editor: CodeEditorWidget; - private _editorFocus: IContextKey; - private _textInputFocus: IContextKey; - private _editorTextFocus: IContextKey; - private _editorTabMovesFocus: IContextKey; - private _editorReadonly: IContextKey; - private _hasMultipleSelections: IContextKey; - private _hasNonEmptySelection: IContextKey; - private _canUndo: IContextKey; - private _canRedo: IContextKey; + private readonly _editor: CodeEditorWidget; + private readonly _editorFocus: IContextKey; + private readonly _textInputFocus: IContextKey; + private readonly _editorTextFocus: IContextKey; + private readonly _editorTabMovesFocus: IContextKey; + private readonly _editorReadonly: IContextKey; + private readonly _hasMultipleSelections: IContextKey; + private readonly _hasNonEmptySelection: IContextKey; + private readonly _canUndo: IContextKey; + private readonly _canRedo: IContextKey; constructor( editor: CodeEditorWidget, @@ -1627,25 +1627,25 @@ class EditorContextKeysManager extends Disposable { export class EditorModeContext extends Disposable { - private _editor: CodeEditorWidget; + private readonly _editor: CodeEditorWidget; - private _langId: IContextKey; - private _hasCompletionItemProvider: IContextKey; - private _hasCodeActionsProvider: IContextKey; - private _hasCodeLensProvider: IContextKey; - private _hasDefinitionProvider: IContextKey; - private _hasDeclarationProvider: IContextKey; - private _hasImplementationProvider: IContextKey; - private _hasTypeDefinitionProvider: IContextKey; - private _hasHoverProvider: IContextKey; - private _hasDocumentHighlightProvider: IContextKey; - private _hasDocumentSymbolProvider: IContextKey; - private _hasReferenceProvider: IContextKey; - private _hasRenameProvider: IContextKey; - private _hasDocumentFormattingProvider: IContextKey; - private _hasDocumentSelectionFormattingProvider: IContextKey; - private _hasSignatureHelpProvider: IContextKey; - private _isInWalkThrough: IContextKey; + private readonly _langId: IContextKey; + private readonly _hasCompletionItemProvider: IContextKey; + private readonly _hasCodeActionsProvider: IContextKey; + private readonly _hasCodeLensProvider: IContextKey; + private readonly _hasDefinitionProvider: IContextKey; + private readonly _hasDeclarationProvider: IContextKey; + private readonly _hasImplementationProvider: IContextKey; + private readonly _hasTypeDefinitionProvider: IContextKey; + private readonly _hasHoverProvider: IContextKey; + private readonly _hasDocumentHighlightProvider: IContextKey; + private readonly _hasDocumentSymbolProvider: IContextKey; + private readonly _hasReferenceProvider: IContextKey; + private readonly _hasRenameProvider: IContextKey; + private readonly _hasDocumentFormattingProvider: IContextKey; + private readonly _hasDocumentSelectionFormattingProvider: IContextKey; + private readonly _hasSignatureHelpProvider: IContextKey; + private readonly _isInWalkThrough: IContextKey; constructor( editor: CodeEditorWidget, @@ -1751,7 +1751,7 @@ export class EditorModeContext extends Disposable { class CodeEditorWidgetFocusTracker extends Disposable { private _hasFocus: boolean; - private _domFocusTracker: dom.IFocusTracker; + private readonly _domFocusTracker: dom.IFocusTracker; private readonly _onChange: Emitter = this._register(new Emitter()); public readonly onChange: Event = this._onChange.event; diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 1f32835046f..d8ee01053ee 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -148,7 +148,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private readonly id: number; - private _domElement: HTMLElement; + private readonly _domElement: HTMLElement; protected readonly _containerDomElement: HTMLElement; private readonly _overviewDomElement: HTMLElement; private readonly _overviewViewportDomElement: FastDomNode; @@ -160,12 +160,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private originalEditor: CodeEditorWidget; private _originalDomNode: HTMLElement; - private _originalEditorState: VisualEditorState; + private readonly _originalEditorState: VisualEditorState; private _originalOverviewRuler: editorBrowser.IOverviewRuler; private modifiedEditor: CodeEditorWidget; private _modifiedDomNode: HTMLElement; - private _modifiedEditorState: VisualEditorState; + private readonly _modifiedEditorState: VisualEditorState; private _modifiedOverviewRuler: editorBrowser.IOverviewRuler; private _currentlyChangingViewZones: boolean; @@ -184,15 +184,15 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private _enableSplitViewResizing: boolean; private _strategy: IDiffEditorWidgetStyle; - private _updateDecorationsRunner: RunOnceScheduler; + private readonly _updateDecorationsRunner: RunOnceScheduler; - private _editorWorkerService: IEditorWorkerService; + private readonly _editorWorkerService: IEditorWorkerService; protected _contextKeyService: IContextKeyService; - private _codeEditorService: ICodeEditorService; - private _themeService: IThemeService; - private _notificationService: INotificationService; + private readonly _codeEditorService: ICodeEditorService; + private readonly _themeService: IThemeService; + private readonly _notificationService: INotificationService; - private _reviewPane: DiffReview; + private readonly _reviewPane: DiffReview; constructor( domElement: HTMLElement, @@ -1251,7 +1251,7 @@ interface IMyViewZone { class ForeignViewZonesIterator { private _index: number; - private _source: IEditorWhitespace[]; + private readonly _source: IEditorWhitespace[]; public current: IEditorWhitespace | null; constructor(source: IEditorWhitespace[]) { @@ -1272,9 +1272,9 @@ class ForeignViewZonesIterator { abstract class ViewZonesComputer { - private lineChanges: editorCommon.ILineChange[]; - private originalForeignVZ: IEditorWhitespace[]; - private modifiedForeignVZ: IEditorWhitespace[]; + private readonly lineChanges: editorCommon.ILineChange[]; + private readonly originalForeignVZ: IEditorWhitespace[]; + private readonly modifiedForeignVZ: IEditorWhitespace[]; constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[]) { this.lineChanges = lineChanges; @@ -1532,7 +1532,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd static MINIMUM_EDITOR_WIDTH = 100; private _disableSash: boolean; - private _sash: Sash; + private readonly _sash: Sash; private _sashRatio: number | null; private _sashPosition: number | null; private _startSashPosition: number; @@ -1911,10 +1911,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor class InlineViewZonesComputer extends ViewZonesComputer { - private originalModel: ITextModel; - private modifiedEditorConfiguration: editorOptions.InternalEditorOptions; - private modifiedEditorTabSize: number; - private renderIndicators: boolean; + private readonly originalModel: ITextModel; + private readonly modifiedEditorConfiguration: editorOptions.InternalEditorOptions; + private readonly modifiedEditorTabSize: number; + private readonly renderIndicators: boolean; constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean) { super(lineChanges, originalForeignVZ, modifiedForeignVZ); diff --git a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts index 5489ac6bea7..1c6f251a3ed 100644 --- a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts +++ b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts @@ -19,8 +19,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib export class EmbeddedCodeEditorWidget extends CodeEditorWidget { - private _parentEditor: ICodeEditor; - private _overwriteOptions: IEditorOptions; + private readonly _parentEditor: ICodeEditor; + private readonly _overwriteOptions: IEditorOptions; constructor( domElement: HTMLElement, @@ -62,8 +62,8 @@ export class EmbeddedCodeEditorWidget extends CodeEditorWidget { export class EmbeddedDiffEditorWidget extends DiffEditorWidget { - private _parentEditor: ICodeEditor; - private _overwriteOptions: IDiffEditorOptions; + private readonly _parentEditor: ICodeEditor; + private readonly _overwriteOptions: IDiffEditorOptions; constructor( domElement: HTMLElement, diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index 28671285ac8..c6cd6494050 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -98,9 +98,9 @@ export class ReplaceCommandWithOffsetCursorState implements ICommand { export class ReplaceCommandThatPreservesSelection implements ICommand { - private _range: Range; - private _text: string; - private _initialSelection: Selection; + private readonly _range: Range; + private readonly _text: string; + private readonly _initialSelection: Selection; private _selectionId: string; constructor(editRange: Range, text: string, initialSelection: Selection) { diff --git a/src/vs/editor/common/commands/shiftCommand.ts b/src/vs/editor/common/commands/shiftCommand.ts index f24790ec137..16ff871c456 100644 --- a/src/vs/editor/common/commands/shiftCommand.ts +++ b/src/vs/editor/common/commands/shiftCommand.ts @@ -68,8 +68,8 @@ export class ShiftCommand implements ICommand { } } - private _opts: IShiftCommandOpts; - private _selection: Selection; + private readonly _opts: IShiftCommandOpts; + private readonly _selection: Selection; private _selectionId: string; private _useLastEditRangeForCursorEndPosition: boolean; private _selectionStartColumnStaysPut: boolean; diff --git a/src/vs/editor/common/commands/surroundSelectionCommand.ts b/src/vs/editor/common/commands/surroundSelectionCommand.ts index 7a6b7274016..ed60c299399 100644 --- a/src/vs/editor/common/commands/surroundSelectionCommand.ts +++ b/src/vs/editor/common/commands/surroundSelectionCommand.ts @@ -9,9 +9,9 @@ import { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/ed import { ITextModel } from 'vs/editor/common/model'; export class SurroundSelectionCommand implements ICommand { - private _range: Selection; - private _charBeforeSelection: string; - private _charAfterSelection: string; + private readonly _range: Selection; + private readonly _charBeforeSelection: string; + private readonly _charAfterSelection: string; constructor(range: Selection, charBeforeSelection: string, charAfterSelection: string) { this._range = range; diff --git a/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts b/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts index 5a9d6e3902b..2d442842b97 100644 --- a/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts +++ b/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts @@ -13,9 +13,9 @@ import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/mod export class TrimTrailingWhitespaceCommand implements ICommand { - private selection: Selection; + private readonly selection: Selection; private selectionId: string; - private cursors: Position[]; + private readonly cursors: Position[]; constructor(selection: Selection, cursors: Position[]) { this.selection = selection; diff --git a/src/vs/editor/common/core/characterClassifier.ts b/src/vs/editor/common/core/characterClassifier.ts index 83b5d93b1df..9d448641d17 100644 --- a/src/vs/editor/common/core/characterClassifier.ts +++ b/src/vs/editor/common/core/characterClassifier.ts @@ -63,7 +63,7 @@ const enum Boolean { export class CharacterSet { - private _actual: CharacterClassifier; + private readonly _actual: CharacterClassifier; constructor() { this._actual = new CharacterClassifier(Boolean.False); diff --git a/src/vs/editor/common/core/uint.ts b/src/vs/editor/common/core/uint.ts index 67556d1a8bc..d89c8043598 100644 --- a/src/vs/editor/common/core/uint.ts +++ b/src/vs/editor/common/core/uint.ts @@ -5,7 +5,7 @@ export class Uint8Matrix { - private _data: Uint8Array; + private readonly _data: Uint8Array; public readonly rows: number; public readonly cols: number; diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index b60b083c1b6..add6b310ea5 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -102,7 +102,7 @@ export interface IUndoRedoResult { export class EditStack { - private model: TextModel; + private readonly model: TextModel; private currentOpenStackElement: IStackElement | null; private past: IStackElement[]; private future: IStackElement[]; diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts index 5f847c76ee3..7b7439f32c4 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -157,10 +157,10 @@ export class StringBuffer { * 2. TreeNode/Buffers normalization should not happen during snapshot reading. */ class PieceTreeSnapshot implements ITextSnapshot { - private _pieces: Piece[]; + private readonly _pieces: Piece[]; private _index: number; - private _tree: PieceTreeBase; - private _BOM: string; + private readonly _tree: PieceTreeBase; + private readonly _BOM: string; constructor(tree: PieceTreeBase, BOM: string) { this._pieces = []; @@ -205,7 +205,7 @@ interface CacheEntry { } class PieceTreeSearchCache { - private _limit: number; + private readonly _limit: number; private _cache: CacheEntry[]; constructor(limit: number) { diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index 1030643a13d..1424533f32f 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -27,8 +27,8 @@ export interface IReverseSingleEditOperation extends IIdentifiedSingleEditOperat } export class PieceTreeTextBuffer implements ITextBuffer { - private _pieceTree: PieceTreeBase; - private _BOM: string; + private readonly _pieceTree: PieceTreeBase; + private readonly _BOM: string; private _mightContainRTL: boolean; private _mightContainNonBasicASCII: boolean; diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts index cfa58453501..5b24e6f1c64 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts @@ -62,12 +62,12 @@ export class PieceTreeTextBufferFactory implements ITextBufferFactory { } export class PieceTreeTextBufferBuilder implements ITextBufferBuilder { - private chunks: StringBuffer[]; + private readonly chunks: StringBuffer[]; private BOM: string; private _hasPreviousChar: boolean; private _previousChar: number; - private _tmpLineStarts: number[]; + private readonly _tmpLineStarts: number[]; private cr: number; private lf: number; diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 1b67ebef2c8..c8fc1231a9b 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -265,8 +265,8 @@ export class TextModel extends Disposable implements model.ITextModel { //#region Tokenization private _languageIdentifier: LanguageIdentifier; - private _tokenizationListener: IDisposable; - private _languageRegistryListener: IDisposable; + private readonly _tokenizationListener: IDisposable; + private readonly _languageRegistryListener: IDisposable; private _revalidateTokensTimeout: any; /*private*/_tokens: ModelLinesTokens; //#endregion @@ -2730,12 +2730,12 @@ class DecorationsTrees { /** * This tree holds decorations that do not show up in the overview ruler. */ - private _decorationsTree0: IntervalTree; + private readonly _decorationsTree0: IntervalTree; /** * This tree holds decorations that show up in the overview ruler. */ - private _decorationsTree1: IntervalTree; + private readonly _decorationsTree1: IntervalTree; constructor() { this._decorationsTree0 = new IntervalTree(); diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index 9f776c68654..1b63ef93f9f 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -509,8 +509,8 @@ export function isValidMatch(wordSeparators: WordCharacterClassifier, text: stri } export class Searcher { - private _wordSeparators: WordCharacterClassifier | null; - private _searchRegex: RegExp; + private readonly _wordSeparators: WordCharacterClassifier | null; + private readonly _searchRegex: RegExp; private _prevMatchStartIndex: number; private _prevMatchLength: number; diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index cff6814a9a7..8387872c18f 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -472,7 +472,7 @@ export class ModelLinesTokens { export class ModelTokensChangedEventBuilder { - private _ranges: { fromLineNumber: number; toLineNumber: number; }[]; + private readonly _ranges: { fromLineNumber: number; toLineNumber: number; }[]; constructor() { this._ranges = []; diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index 10919a8f31f..dbed73b8b7f 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -7,7 +7,7 @@ import { IMode, LanguageIdentifier } from 'vs/editor/common/modes'; export class FrankensteinMode implements IMode { - private _languageIdentifier: LanguageIdentifier; + private readonly _languageIdentifier: LanguageIdentifier; constructor(languageIdentifier: LanguageIdentifier) { this._languageIdentifier = languageIdentifier; diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index 1c46797d5e7..8bea5db7e8d 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -175,7 +175,7 @@ export class LanguageConfigurationChangeEvent { export class LanguageConfigurationRegistryImpl { - private _entries: RichEditSupport[]; + private readonly _entries: RichEditSupport[]; private readonly _onDidChange = new Emitter(); public readonly onDidChange: Event = this._onDidChange.event; diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index 37b10402317..25c1c221e5b 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -29,7 +29,7 @@ function isExclusive(selector: LanguageSelector): boolean { export class LanguageFeatureRegistry { private _clock: number = 0; - private _entries: Entry[] = []; + private readonly _entries: Entry[] = []; private readonly _onDidChange = new Emitter(); constructor() { diff --git a/src/vs/editor/common/modes/linkComputer.ts b/src/vs/editor/common/modes/linkComputer.ts index 290b424ee2d..00bf7d01b36 100644 --- a/src/vs/editor/common/modes/linkComputer.ts +++ b/src/vs/editor/common/modes/linkComputer.ts @@ -35,8 +35,8 @@ export type Edge = [State, number, State]; export class StateMachine { - private _states: Uint8Matrix; - private _maxCharCode: number; + private readonly _states: Uint8Matrix; + private readonly _maxCharCode: number; constructor(edges: Edge[]) { let maxCharCode = 0; diff --git a/src/vs/editor/common/modes/modesRegistry.ts b/src/vs/editor/common/modes/modesRegistry.ts index ea7a8f05d1a..fbdda5d65a4 100644 --- a/src/vs/editor/common/modes/modesRegistry.ts +++ b/src/vs/editor/common/modes/modesRegistry.ts @@ -17,7 +17,7 @@ export const Extensions = { export class EditorModesRegistry { - private _languages: ILanguageExtensionPoint[]; + private readonly _languages: ILanguageExtensionPoint[]; private _dynamicLanguages: ILanguageExtensionPoint[]; private readonly _onDidChangeLanguages = new Emitter(); diff --git a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts index d49dc63f57e..3ca8affc18f 100644 --- a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts +++ b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts @@ -64,7 +64,7 @@ export class BasicInplaceReplace { return null; } - private _defaultValueSet: string[][] = [ + private readonly _defaultValueSet: string[][] = [ ['true', 'false'], ['True', 'False'], ['Private', 'Public', 'Friend', 'ReadOnly', 'Partial', 'Protected', 'WriteOnly'], diff --git a/src/vs/editor/common/modes/supports/tokenization.ts b/src/vs/editor/common/modes/supports/tokenization.ts index d245a41fb89..12566c3b00e 100644 --- a/src/vs/editor/common/modes/supports/tokenization.ts +++ b/src/vs/editor/common/modes/supports/tokenization.ts @@ -151,8 +151,8 @@ const colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/; export class ColorMap { private _lastColorId: number; - private _id2color: Color[]; - private _color2id: Map; + private readonly _id2color: Color[]; + private readonly _color2id: Map; constructor() { this._lastColorId = 0; diff --git a/src/vs/editor/common/modes/tokenizationRegistry.ts b/src/vs/editor/common/modes/tokenizationRegistry.ts index 158608f91e4..82ad12da605 100644 --- a/src/vs/editor/common/modes/tokenizationRegistry.ts +++ b/src/vs/editor/common/modes/tokenizationRegistry.ts @@ -10,8 +10,8 @@ import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupp export class TokenizationRegistryImpl implements ITokenizationRegistry { - private _map: { [language: string]: ITokenizationSupport }; - private _promises: { [language: string]: Thenable }; + private readonly _map: { [language: string]: ITokenizationSupport }; + private readonly _promises: { [language: string]: Thenable }; private readonly _onDidChange = new Emitter(); public readonly onDidChange: Event = this._onDidChange.event; diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index f5564b6f567..acbc2fe7795 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -323,7 +323,7 @@ declare var require: any; * @internal */ export abstract class BaseEditorSimpleWorker { - private _foreignModuleFactory: IForeignModuleFactory | null; + private readonly _foreignModuleFactory: IForeignModuleFactory | null; private _foreignModule: any; constructor(foreignModuleFactory: IForeignModuleFactory | null) { diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 501de316cb7..d427f63ebad 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -146,7 +146,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { class WorkerManager extends Disposable { - private _modelService: IModelService; + private readonly _modelService: IModelService; private _editorWorkerClient: EditorWorkerClient | null; private _lastWorkerUsedTime: number; @@ -211,8 +211,8 @@ class WorkerManager extends Disposable { class EditorModelManager extends Disposable { - private _proxy: EditorSimpleWorkerImpl; - private _modelService: IModelService; + private readonly _proxy: EditorSimpleWorkerImpl; + private readonly _modelService: IModelService; private _syncedModels: { [modelUrl: string]: IDisposable[]; } = Object.create(null); private _syncedModelsLastUsedTime: { [modelUrl: string]: number; } = Object.create(null); @@ -312,8 +312,8 @@ interface IWorkerClient { } class SynchronousWorkerClient implements IWorkerClient { - private _instance: T; - private _proxyObj: Promise; + private readonly _instance: T; + private readonly _proxyObj: Promise; constructor(instance: T) { this._instance = instance; @@ -331,9 +331,9 @@ class SynchronousWorkerClient implements IWorkerClient export class EditorWorkerClient extends Disposable { - private _modelService: IModelService; + private readonly _modelService: IModelService; private _worker: IWorkerClient | null; - private _workerFactory: DefaultWorkerFactory; + private readonly _workerFactory: DefaultWorkerFactory; private _modelManager: EditorModelManager | null; constructor(modelService: IModelService, label: string | undefined) { diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index 5534b442510..a57f2096f36 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -36,8 +36,8 @@ export class LanguagesRegistry extends Disposable { private readonly _warnOnOverwrite: boolean; private _nextLanguageId2: number; - private _languageIdToLanguage: string[]; - private _languageToLanguageId: { [id: string]: number; }; + private readonly _languageIdToLanguage: string[]; + private readonly _languageToLanguageId: { [id: string]: number; }; private _languages: { [id: string]: IResolvedLanguage; }; private _mimeTypesMap: { [mimeType: string]: LanguageIdentifier; }; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 135d4303ac4..4357d27d9c7 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -91,9 +91,9 @@ const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLin export class ModelServiceImpl extends Disposable implements IModelService { public _serviceBrand: any; - private _configurationService: IConfigurationService; - private _configurationServiceSubscription: IDisposable; - private _resourcePropertiesService: ITextResourcePropertiesService; + private readonly _configurationService: IConfigurationService; + private readonly _configurationServiceSubscription: IDisposable; + private readonly _resourcePropertiesService: ITextResourcePropertiesService; private readonly _onModelAdded: Emitter = this._register(new Emitter()); public readonly onModelAdded: Event = this._onModelAdded.event; @@ -111,7 +111,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { /** * All the models known in the system. */ - private _models: { [modelId: string]: ModelData; }; + private readonly _models: { [modelId: string]: ModelData; }; constructor( @IConfigurationService configurationService: IConfigurationService, diff --git a/src/vs/editor/common/services/webWorker.ts b/src/vs/editor/common/services/webWorker.ts index 4e54ac849a4..a75cd977352 100644 --- a/src/vs/editor/common/services/webWorker.ts +++ b/src/vs/editor/common/services/webWorker.ts @@ -52,7 +52,7 @@ export interface IWebWorkerOptions { class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWorker { - private _foreignModuleId: string; + private readonly _foreignModuleId: string; private _foreignModuleCreateData: any | null; private _foreignProxy: Promise | null; diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index 24c204f5c13..c34c29d7f2e 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -75,7 +75,7 @@ export class OverviewRulerZone { export class OverviewZoneManager { - private _getVerticalOffsetForLine: (lineNumber: number) => number; + private readonly _getVerticalOffsetForLine: (lineNumber: number) => number; private _zones: OverviewRulerZone[]; private _colorZonesInvalid: boolean; private _lineHeight: number; @@ -85,8 +85,8 @@ export class OverviewZoneManager { private _pixelRatio: number; private _lastAssignedId: number; - private _color2Id: { [color: string]: number; }; - private _id2Color: string[]; + private readonly _color2Id: { [color: string]: number; }; + private readonly _id2Color: string[]; constructor(getVerticalOffsetForLine: (lineNumber: number) => number) { this._getVerticalOffsetForLine = getVerticalOffsetForLine; diff --git a/src/vs/editor/common/view/viewEventDispatcher.ts b/src/vs/editor/common/view/viewEventDispatcher.ts index 47e26f7916d..54bd7a6e986 100644 --- a/src/vs/editor/common/view/viewEventDispatcher.ts +++ b/src/vs/editor/common/view/viewEventDispatcher.ts @@ -8,8 +8,8 @@ import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; export class ViewEventDispatcher { - private _eventHandlerGateKeeper: (callback: () => void) => void; - private _eventHandlers: ViewEventHandler[]; + private readonly _eventHandlerGateKeeper: (callback: () => void) => void; + private readonly _eventHandlers: ViewEventHandler[]; private _eventQueue: ViewEvent[] | null; private _isConsumingQueue: boolean; diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index ed6cfcfe507..5e79341a942 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -102,8 +102,8 @@ export class DecorationSegment { class Stack { public count: number; - private stopOffsets: number[]; - private classNames: string[]; + private readonly stopOffsets: number[]; + private readonly classNames: string[]; constructor() { this.stopOffsets = []; diff --git a/src/vs/editor/common/viewLayout/linesLayout.ts b/src/vs/editor/common/viewLayout/linesLayout.ts index f48f66bae7e..2967fb3b003 100644 --- a/src/vs/editor/common/viewLayout/linesLayout.ts +++ b/src/vs/editor/common/viewLayout/linesLayout.ts @@ -30,7 +30,7 @@ export class LinesLayout { /** * Contains whitespace information in pixels */ - private _whitespaces: WhitespaceComputer; + private readonly _whitespaces: WhitespaceComputer; constructor(lineCount: number, lineHeight: number) { this._lineCount = lineCount; diff --git a/src/vs/editor/common/viewLayout/whitespaceComputer.ts b/src/vs/editor/common/viewLayout/whitespaceComputer.ts index 1177a572199..537c36ac807 100644 --- a/src/vs/editor/common/viewLayout/whitespaceComputer.ts +++ b/src/vs/editor/common/viewLayout/whitespaceComputer.ts @@ -18,27 +18,27 @@ export class WhitespaceComputer { /** * heights[i] is the height in pixels for whitespace at index i */ - private _heights: number[]; + private readonly _heights: number[]; /** * minWidths[i] is the min width in pixels for whitespace at index i */ - private _minWidths: number[]; + private readonly _minWidths: number[]; /** * afterLineNumbers[i] is the line number whitespace at index i is after */ - private _afterLineNumbers: number[]; + private readonly _afterLineNumbers: number[]; /** * ordinals[i] is the orinal of the whitespace at index i */ - private _ordinals: number[]; + private readonly _ordinals: number[]; /** * prefixSum[i] = SUM(heights[j]), 1 <= j <= i */ - private _prefixSum: number[]; + private readonly _prefixSum: number[]; /** * prefixSum[i], 1 <= i <= prefixSumValidIndex can be trusted @@ -48,12 +48,12 @@ export class WhitespaceComputer { /** * ids[i] is the whitespace id of whitespace at index i */ - private _ids: number[]; + private readonly _ids: number[]; /** * index at which a whitespace is positioned (inside heights, afterLineNumbers, prefixSum members) */ - private _whitespaceId2Index: { + private readonly _whitespaceId2Index: { [id: string]: number; }; diff --git a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts index 040c0108e56..9833c7c50c1 100644 --- a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts +++ b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts @@ -56,7 +56,7 @@ class WrappingCharacterClassifier extends CharacterClassifier { export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactory { - private classifier: WrappingCharacterClassifier; + private readonly classifier: WrappingCharacterClassifier; constructor(breakBeforeChars: string, breakAfterChars: string, breakObtrusiveChars: string) { this.classifier = new WrappingCharacterClassifier(breakBeforeChars, breakAfterChars, breakObtrusiveChars); @@ -255,8 +255,8 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor export class CharacterHardWrappingLineMapping implements ILineMapping { - private _prefixSums: PrefixSumComputer; - private _wrappedLinesIndent: string; + private readonly _prefixSums: PrefixSumComputer; + private readonly _wrappedLinesIndent: string; constructor(prefixSums: PrefixSumComputer, wrappedLinesIndent: string) { this._prefixSums = prefixSums; diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts index e3144d866dc..81e66ac5059 100644 --- a/src/vs/editor/common/viewModel/prefixSumComputer.ts +++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts @@ -32,7 +32,7 @@ export class PrefixSumComputer { /** * prefixSum[i], 0 <= i <= prefixSumValidIndex can be trusted */ - private prefixSumValidIndex: Int32Array; + private readonly prefixSumValidIndex: Int32Array; constructor(values: Uint32Array) { this.values = values; diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 13bf1b6f800..75b8b3739e5 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -149,7 +149,7 @@ const enum IndentGuideRepeatOption { export class SplitLinesCollection implements IViewModelLinesCollection { - private model: ITextModel; + private readonly model: ITextModel; private _validModelVersionId: number; private wrappingColumn: number; @@ -160,7 +160,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { private prefixSumComputer: PrefixSumComputerWithCache; - private linePositionMapperFactory: ILineMapperFactory; + private readonly linePositionMapperFactory: ILineMapperFactory; private hiddenAreasIds: string[]; @@ -1001,11 +1001,11 @@ class InvisibleIdentitySplitLine implements ISplitLine { export class SplitLine implements ISplitLine { - private positionMapper: ILineMapping; - private outputLineCount: number; + private readonly positionMapper: ILineMapping; + private readonly outputLineCount: number; - private wrappedIndent: string; - private wrappedIndentLength: number; + private readonly wrappedIndent: string; + private readonly wrappedIndentLength: number; private _isVisible: boolean; constructor(positionMapper: ILineMapping, isVisible: boolean) { diff --git a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts index 62dea606561..672b156378a 100644 --- a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts +++ b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts @@ -92,7 +92,7 @@ export class BracketMatchingController extends Disposable implements editorCommo private _lastBracketsData: BracketsData[]; private _lastVersionId: number; private _decorations: string[]; - private _updateBracketsSoon: RunOnceScheduler; + private readonly _updateBracketsSoon: RunOnceScheduler; private _matchBrackets: boolean; constructor( diff --git a/src/vs/editor/contrib/caretOperations/caretOperations.ts b/src/vs/editor/contrib/caretOperations/caretOperations.ts index f3a753dbc7b..3b715b871e7 100644 --- a/src/vs/editor/contrib/caretOperations/caretOperations.ts +++ b/src/vs/editor/contrib/caretOperations/caretOperations.ts @@ -12,7 +12,7 @@ import { MoveCaretCommand } from 'vs/editor/contrib/caretOperations/moveCaretCom class MoveCaretAction extends EditorAction { - private left: boolean; + private readonly left: boolean; constructor(left: boolean, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/caretOperations/moveCaretCommand.ts b/src/vs/editor/contrib/caretOperations/moveCaretCommand.ts index 0c55d207603..d992856345c 100644 --- a/src/vs/editor/contrib/caretOperations/moveCaretCommand.ts +++ b/src/vs/editor/contrib/caretOperations/moveCaretCommand.ts @@ -10,8 +10,8 @@ import { ITextModel } from 'vs/editor/common/model'; export class MoveCaretCommand implements ICommand { - private _selection: Selection; - private _isMovingLeft: boolean; + private readonly _selection: Selection; + private readonly _isMovingLeft: boolean; private _cutStartIndex: number; private _cutEndIndex: number; diff --git a/src/vs/editor/contrib/clipboard/clipboard.ts b/src/vs/editor/contrib/clipboard/clipboard.ts index 5e43f1b39ef..990be3a2987 100644 --- a/src/vs/editor/contrib/clipboard/clipboard.ts +++ b/src/vs/editor/contrib/clipboard/clipboard.ts @@ -32,7 +32,7 @@ type ExecCommand = 'cut' | 'copy' | 'paste'; abstract class ExecCommandAction extends EditorAction { - private browserCommand: ExecCommand; + private readonly browserCommand: ExecCommand; constructor(browserCommand: ExecCommand, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/codeAction/codeActionCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts index 4c5ee4309ca..76a522e6a55 100644 --- a/src/vs/editor/contrib/codeAction/codeActionCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -42,11 +42,11 @@ export class QuickFixController implements IEditorContribution { return editor.getContribution(QuickFixController.ID); } - private _editor: ICodeEditor; - private _model: CodeActionModel; - private _codeActionContextMenu: CodeActionContextMenu; - private _lightBulbWidget: LightBulbWidget; - private _disposables: IDisposable[] = []; + private readonly _editor: ICodeEditor; + private readonly _model: CodeActionModel; + private readonly _codeActionContextMenu: CodeActionContextMenu; + private readonly _lightBulbWidget: LightBulbWidget; + private readonly _disposables: IDisposable[] = []; private _activeRequest: CancelablePromise | undefined; diff --git a/src/vs/editor/contrib/codeAction/codeActionModel.ts b/src/vs/editor/contrib/codeAction/codeActionModel.ts index 5673569e465..f252c75ef8a 100644 --- a/src/vs/editor/contrib/codeAction/codeActionModel.ts +++ b/src/vs/editor/contrib/codeAction/codeActionModel.ts @@ -26,9 +26,9 @@ export class CodeActionOracle { private readonly _autoTriggerTimer = new TimeoutTimer(); constructor( - private _editor: ICodeEditor, + private readonly _editor: ICodeEditor, private readonly _markerService: IMarkerService, - private _signalChange: (newState: CodeActionsState.State) => void, + private readonly _signalChange: (newState: CodeActionsState.State) => void, private readonly _delay: number = 250, private readonly _progressService?: IProgressService, ) { diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index 924c840ea3f..f1681995636 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -33,7 +33,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { private _detectVisibleLenses: RunOnceScheduler; constructor( - private _editor: editorBrowser.ICodeEditor, + private readonly _editor: editorBrowser.ICodeEditor, @ICommandService private readonly _commandService: ICommandService, @INotificationService private readonly _notificationService: INotificationService ) { diff --git a/src/vs/editor/contrib/codelens/codelensWidget.ts b/src/vs/editor/contrib/codelens/codelensWidget.ts index e9f8892a1d2..19265ebabc2 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.ts +++ b/src/vs/editor/contrib/codelens/codelensWidget.ts @@ -26,7 +26,7 @@ class CodeLensViewZone implements editorBrowser.IViewZone { afterLineNumber: number; private _lastHeight: number; - private _onHeight: Function; + private readonly _onHeight: Function; constructor(afterLineNumber: number, onHeight: Function) { this.afterLineNumber = afterLineNumber; @@ -164,9 +164,9 @@ export interface IDecorationIdCallback { export class CodeLensHelper { - private _removeDecorations: string[]; - private _addDecorations: IModelDeltaDecoration[]; - private _addDecorationsCallbacks: IDecorationIdCallback[]; + private readonly _removeDecorations: string[]; + private readonly _addDecorations: IModelDeltaDecoration[]; + private readonly _addDecorationsCallbacks: IDecorationIdCallback[]; constructor() { this._removeDecorations = []; diff --git a/src/vs/editor/contrib/colorPicker/colorDetector.ts b/src/vs/editor/contrib/colorPicker/colorDetector.ts index 02be8db0cae..1de0bda0312 100644 --- a/src/vs/editor/contrib/colorPicker/colorDetector.ts +++ b/src/vs/editor/contrib/colorPicker/colorDetector.ts @@ -37,11 +37,11 @@ export class ColorDetector implements IEditorContribution { private _colorDatas = new Map(); private _colorDecoratorIds: string[] = []; - private _decorationsTypes: { [key: string]: boolean } = {}; + private readonly _decorationsTypes: { [key: string]: boolean } = {}; private _isEnabled: boolean; - constructor(private _editor: ICodeEditor, + constructor(private readonly _editor: ICodeEditor, @ICodeEditorService private readonly _codeEditorService: ICodeEditorService, @IConfigurationService private readonly _configurationService: IConfigurationService ) { diff --git a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts index 30536ea190f..e225e6a844e 100644 --- a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts +++ b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts @@ -19,11 +19,11 @@ const $ = dom.$; export class ColorPickerHeader extends Disposable { - private domNode: HTMLElement; - private pickedColorNode: HTMLElement; + private readonly domNode: HTMLElement; + private readonly pickedColorNode: HTMLElement; private backgroundColor: Color; - constructor(container: HTMLElement, private model: ColorPickerModel, themeService: IThemeService) { + constructor(container: HTMLElement, private readonly model: ColorPickerModel, themeService: IThemeService) { super(); this.domNode = $('.colorpicker-header'); @@ -63,12 +63,12 @@ export class ColorPickerHeader extends Disposable { export class ColorPickerBody extends Disposable { - private domNode: HTMLElement; - private saturationBox: SaturationBox; - private hueStrip: Strip; - private opacityStrip: Strip; + private readonly domNode: HTMLElement; + private readonly saturationBox: SaturationBox; + private readonly hueStrip: Strip; + private readonly opacityStrip: Strip; - constructor(container: HTMLElement, private model: ColorPickerModel, private pixelRatio: number) { + constructor(container: HTMLElement, private readonly model: ColorPickerModel, private pixelRatio: number) { super(); this.domNode = $('.colorpicker-body'); @@ -120,9 +120,9 @@ export class ColorPickerBody extends Disposable { class SaturationBox extends Disposable { - private domNode: HTMLElement; - private selection: HTMLElement; - private canvas: HTMLCanvasElement; + private readonly domNode: HTMLElement; + private readonly selection: HTMLElement; + private readonly canvas: HTMLCanvasElement; private width: number; private height: number; @@ -133,7 +133,7 @@ class SaturationBox extends Disposable { private _onColorFlushed = new Emitter(); readonly onColorFlushed: Event = this._onColorFlushed.event; - constructor(container: HTMLElement, private model: ColorPickerModel, private pixelRatio: number) { + constructor(container: HTMLElement, private readonly model: ColorPickerModel, private pixelRatio: number) { super(); this.domNode = $('.saturation-wrap'); @@ -335,7 +335,7 @@ export class ColorPickerWidget extends Widget { body: ColorPickerBody; - constructor(container: Node, private model: ColorPickerModel, private pixelRatio: number, themeService: IThemeService) { + constructor(container: Node, private readonly model: ColorPickerModel, private pixelRatio: number, themeService: IThemeService) { super(); this._register(onDidChangeZoomLevel(() => this.layout())); diff --git a/src/vs/editor/contrib/comment/blockCommentCommand.ts b/src/vs/editor/contrib/comment/blockCommentCommand.ts index 012b6243468..5c5273c9c35 100644 --- a/src/vs/editor/contrib/comment/blockCommentCommand.ts +++ b/src/vs/editor/contrib/comment/blockCommentCommand.ts @@ -14,7 +14,7 @@ import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageCo export class BlockCommentCommand implements editorCommon.ICommand { - private _selection: Selection; + private readonly _selection: Selection; private _usedEndToken: string | null; constructor(selection: Selection) { diff --git a/src/vs/editor/contrib/comment/comment.ts b/src/vs/editor/contrib/comment/comment.ts index 454e6073f51..5c6118a3f6f 100644 --- a/src/vs/editor/contrib/comment/comment.ts +++ b/src/vs/editor/contrib/comment/comment.ts @@ -16,7 +16,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis abstract class CommentLineAction extends EditorAction { - private _type: Type; + private readonly _type: Type; constructor(type: Type, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/comment/lineCommentCommand.ts b/src/vs/editor/contrib/comment/lineCommentCommand.ts index 5bc743096c7..26b3f9e9111 100644 --- a/src/vs/editor/contrib/comment/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/lineCommentCommand.ts @@ -48,12 +48,12 @@ export const enum Type { export class LineCommentCommand implements editorCommon.ICommand { - private _selection: Selection; + private readonly _selection: Selection; private _selectionId: string; private _deltaColumn: number; private _moveEndPositionDown: boolean; - private _tabSize: number; - private _type: Type; + private readonly _tabSize: number; + private readonly _type: Type; constructor(selection: Selection, tabSize: number, type: Type) { this._selection = selection; diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts index 0b3261cdff3..8a27b553e5e 100644 --- a/src/vs/editor/contrib/contextmenu/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts @@ -32,7 +32,7 @@ export class ContextMenuController implements IEditorContribution { private _toDispose: IDisposable[] = []; private _contextMenuIsBeingShownCount: number = 0; - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; constructor( editor: ICodeEditor, diff --git a/src/vs/editor/contrib/dnd/dnd.ts b/src/vs/editor/contrib/dnd/dnd.ts index a716d8fa10d..44a5dd539e2 100644 --- a/src/vs/editor/contrib/dnd/dnd.ts +++ b/src/vs/editor/contrib/dnd/dnd.ts @@ -32,7 +32,7 @@ export class DragAndDropController implements editorCommon.IEditorContribution { private static readonly ID = 'editor.contrib.dragAndDrop'; - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _toUnhook: IDisposable[]; private _dragSelection: Selection | null; private _dndDecorationIds: string[]; diff --git a/src/vs/editor/contrib/dnd/dragAndDropCommand.ts b/src/vs/editor/contrib/dnd/dragAndDropCommand.ts index 9942dc85260..12d405648c9 100644 --- a/src/vs/editor/contrib/dnd/dragAndDropCommand.ts +++ b/src/vs/editor/contrib/dnd/dragAndDropCommand.ts @@ -12,10 +12,10 @@ import { ITextModel } from 'vs/editor/common/model'; export class DragAndDropCommand implements editorCommon.ICommand { - private selection: Selection; - private targetPosition: Position; + private readonly selection: Selection; + private readonly targetPosition: Position; private targetSelection: Selection; - private copy: boolean; + private readonly copy: boolean; constructor(selection: Selection, targetPosition: Position, copy: boolean) { this.selection = selection; diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 06d8c1bf07a..d51962cdfef 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -71,12 +71,12 @@ export class CommonFindController extends Disposable implements editorCommon.IEd private static readonly ID = 'editor.contrib.findController'; protected _editor: ICodeEditor; - private _findWidgetVisible: IContextKey; + private readonly _findWidgetVisible: IContextKey; protected _state: FindReplaceState; protected _updateHistoryDelayer: Delayer; private _model: FindModelBoundToEditorModel | null; - private _storageService: IStorageService; - private _clipboardService: IClipboardService; + private readonly _storageService: IStorageService; + private readonly _clipboardService: IClipboardService; protected readonly _contextKeyService: IContextKeyService; public static get(editor: ICodeEditor): CommonFindController { diff --git a/src/vs/editor/contrib/find/findDecorations.ts b/src/vs/editor/contrib/find/findDecorations.ts index 6c90044a369..bb115977387 100644 --- a/src/vs/editor/contrib/find/findDecorations.ts +++ b/src/vs/editor/contrib/find/findDecorations.ts @@ -14,7 +14,7 @@ import { themeColorFromId } from 'vs/platform/theme/common/themeService'; export class FindDecorations implements IDisposable { - private _editor: IActiveCodeEditor; + private readonly _editor: IActiveCodeEditor; private _decorations: string[]; private _overviewRulerApproximateDecorations: string[]; private _findScopeDecorationId: string | null; diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index 59ab1deb7e9..9264aa9b734 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -69,14 +69,14 @@ const RESEARCH_DELAY = 240; export class FindModelBoundToEditorModel { - private _editor: IActiveCodeEditor; - private _state: FindReplaceState; + private readonly _editor: IActiveCodeEditor; + private readonly _state: FindReplaceState; private _toDispose: IDisposable[]; - private _decorations: FindDecorations; + private readonly _decorations: FindDecorations; private _ignoreModelContentChanged: boolean; - private _startSearchingTimer: TimeoutTimer; + private readonly _startSearchingTimer: TimeoutTimer; - private _updateDecorationsScheduler: RunOnceScheduler; + private readonly _updateDecorationsScheduler: RunOnceScheduler; private _isDisposed: boolean; constructor(editor: IActiveCodeEditor, state: FindReplaceState) { diff --git a/src/vs/editor/contrib/find/findOptionsWidget.ts b/src/vs/editor/contrib/find/findOptionsWidget.ts index 768bb6adaeb..8a61aabd766 100644 --- a/src/vs/editor/contrib/find/findOptionsWidget.ts +++ b/src/vs/editor/contrib/find/findOptionsWidget.ts @@ -18,14 +18,14 @@ export class FindOptionsWidget extends Widget implements IOverlayWidget { private static readonly ID = 'editor.contrib.findOptionsWidget'; - private _editor: ICodeEditor; - private _state: FindReplaceState; - private _keybindingService: IKeybindingService; + private readonly _editor: ICodeEditor; + private readonly _state: FindReplaceState; + private readonly _keybindingService: IKeybindingService; - private _domNode: HTMLElement; - private regex: RegexCheckbox; - private wholeWords: WholeWordsCheckbox; - private caseSensitive: CaseSensitiveCheckbox; + private readonly _domNode: HTMLElement; + private readonly regex: RegexCheckbox; + private readonly wholeWords: WholeWordsCheckbox; + private readonly caseSensitive: CaseSensitiveCheckbox; constructor( editor: ICodeEditor, diff --git a/src/vs/editor/contrib/find/findWidget.ts b/src/vs/editor/contrib/find/findWidget.ts index 15b4b0bf4d3..2c9046b5298 100644 --- a/src/vs/editor/contrib/find/findWidget.ts +++ b/src/vs/editor/contrib/find/findWidget.ts @@ -84,8 +84,8 @@ export class FindWidgetViewZone implements IViewZone { export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSashLayoutProvider { private static readonly ID = 'editor.contrib.findWidget'; private readonly _codeEditor: ICodeEditor; - private _state: FindReplaceState; - private _controller: IFindController; + private readonly _state: FindReplaceState; + private readonly _controller: IFindController; private readonly _contextViewProvider: IContextViewProvider; private readonly _keybindingService: IKeybindingService; private readonly _contextKeyService: IContextKeyService; @@ -107,16 +107,16 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas private _isReplaceVisible: boolean; private _ignoreChangeEvent: boolean; - private _findFocusTracker: dom.IFocusTracker; - private _findInputFocused: IContextKey; - private _replaceFocusTracker: dom.IFocusTracker; - private _replaceInputFocused: IContextKey; + private readonly _findFocusTracker: dom.IFocusTracker; + private readonly _findInputFocused: IContextKey; + private readonly _replaceFocusTracker: dom.IFocusTracker; + private readonly _replaceInputFocused: IContextKey; private _viewZone?: FindWidgetViewZone; private _viewZoneId?: number; private _resizeSash: Sash; private _resized: boolean; - private _updateHistoryDelayer: Delayer; + private readonly _updateHistoryDelayer: Delayer; constructor( codeEditor: ICodeEditor, diff --git a/src/vs/editor/contrib/find/replaceAllCommand.ts b/src/vs/editor/contrib/find/replaceAllCommand.ts index 304fbcb4c6a..1b542d6cb0b 100644 --- a/src/vs/editor/contrib/find/replaceAllCommand.ts +++ b/src/vs/editor/contrib/find/replaceAllCommand.ts @@ -15,10 +15,10 @@ interface IEditOperation { export class ReplaceAllCommand implements editorCommon.ICommand { - private _editorSelection: Selection; + private readonly _editorSelection: Selection; private _trackedEditorSelectionId: string; - private _ranges: Range[]; - private _replaceStrings: string[]; + private readonly _ranges: Range[]; + private readonly _replaceStrings: string[]; constructor(editorSelection: Selection, ranges: Range[], replaceStrings: string[]) { this._editorSelection = editorSelection; diff --git a/src/vs/editor/contrib/find/simpleFindWidget.ts b/src/vs/editor/contrib/find/simpleFindWidget.ts index 3334c2fa6bf..40371f2c9fe 100644 --- a/src/vs/editor/contrib/find/simpleFindWidget.ts +++ b/src/vs/editor/contrib/find/simpleFindWidget.ts @@ -25,13 +25,13 @@ const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next mat const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); export abstract class SimpleFindWidget extends Widget { - private _findInput: FindInput; - private _domNode: HTMLElement; - private _innerDomNode: HTMLElement; + private readonly _findInput: FindInput; + private readonly _domNode: HTMLElement; + private readonly _innerDomNode: HTMLElement; private _isVisible: boolean = false; - private _focusTracker: dom.IFocusTracker; - private _findInputFocusTracker: dom.IFocusTracker; - private _updateHistoryDelayer: Delayer; + private readonly _focusTracker: dom.IFocusTracker; + private readonly _findInputFocusTracker: dom.IFocusTracker; + private readonly _updateHistoryDelayer: Delayer; constructor( @IContextViewService private readonly _contextViewService: IContextViewService, diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index e8393a98ce2..24d64b50225 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -55,12 +55,12 @@ export class FoldingController implements IEditorContribution { return editor.getContribution(ID); } - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private _isEnabled: boolean; private _autoHideFoldingControls: boolean; private _useFoldingProviders: boolean; - private foldingDecorationProvider: FoldingDecorationProvider; + private readonly foldingDecorationProvider: FoldingDecorationProvider; private foldingModel: FoldingModel | null; private hiddenRangeModel: HiddenRangeModel | null; diff --git a/src/vs/editor/contrib/folding/foldingDecorations.ts b/src/vs/editor/contrib/folding/foldingDecorations.ts index 17359b411fb..4b55e86f6fa 100644 --- a/src/vs/editor/contrib/folding/foldingDecorations.ts +++ b/src/vs/editor/contrib/folding/foldingDecorations.ts @@ -28,7 +28,7 @@ export class FoldingDecorationProvider implements IDecorationProvider { public autoHideFoldingControls: boolean = true; - constructor(private editor: ICodeEditor) { + constructor(private readonly editor: ICodeEditor) { } getDecorationOption(isCollapsed: boolean): ModelDecorationOptions { diff --git a/src/vs/editor/contrib/folding/foldingModel.ts b/src/vs/editor/contrib/folding/foldingModel.ts index da25d5193dd..eb0db3e5b3a 100644 --- a/src/vs/editor/contrib/folding/foldingModel.ts +++ b/src/vs/editor/contrib/folding/foldingModel.ts @@ -21,8 +21,8 @@ export interface FoldingModelChangeEvent { export type CollapseMemento = ILineRange[]; export class FoldingModel { - private _textModel: ITextModel; - private _decorationProvider: IDecorationProvider; + private readonly _textModel: ITextModel; + private readonly _decorationProvider: IDecorationProvider; private _regions: FoldingRegions; private _editorDecorationIds: string[]; diff --git a/src/vs/editor/contrib/folding/foldingRanges.ts b/src/vs/editor/contrib/folding/foldingRanges.ts index bdd2558322d..e8a7cd7adef 100644 --- a/src/vs/editor/contrib/folding/foldingRanges.ts +++ b/src/vs/editor/contrib/folding/foldingRanges.ts @@ -14,11 +14,11 @@ export const MAX_LINE_NUMBER = 0xFFFFFF; const MASK_INDENT = 0xFF000000; export class FoldingRegions { - private _startIndexes: Uint32Array; - private _endIndexes: Uint32Array; - private _collapseStates: Uint32Array; + private readonly _startIndexes: Uint32Array; + private readonly _endIndexes: Uint32Array; + private readonly _collapseStates: Uint32Array; private _parentsComputed: boolean; - private _types: Array | undefined; + private readonly _types: Array | undefined; constructor(startIndexes: Uint32Array, endIndexes: Uint32Array, types?: Array) { if (startIndexes.length !== endIndexes.length || startIndexes.length > MAX_FOLDING_REGIONS) { @@ -154,7 +154,7 @@ export class FoldingRegions { export class FoldingRegion { - constructor(private ranges: FoldingRegions, private index: number) { + constructor(private readonly ranges: FoldingRegions, private index: number) { } public get startLineNumber() { diff --git a/src/vs/editor/contrib/folding/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/hiddenRangeModel.ts index d93e3c6b823..96205183819 100644 --- a/src/vs/editor/contrib/folding/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/hiddenRangeModel.ts @@ -11,7 +11,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { findFirstInSorted } from 'vs/base/common/arrays'; export class HiddenRangeModel { - private _foldingModel: FoldingModel; + private readonly _foldingModel: FoldingModel; private _hiddenRanges: IRange[]; private _foldingModelListener: IDisposable | null; private _updateEventEmitter = new Emitter(); diff --git a/src/vs/editor/contrib/folding/indentRangeProvider.ts b/src/vs/editor/contrib/folding/indentRangeProvider.ts index 894482f017d..266a104d30a 100644 --- a/src/vs/editor/contrib/folding/indentRangeProvider.ts +++ b/src/vs/editor/contrib/folding/indentRangeProvider.ts @@ -20,7 +20,7 @@ export class IndentRangeProvider implements RangeProvider { readonly decorations; - constructor(private editorModel: ITextModel) { + constructor(private readonly editorModel: ITextModel) { } dispose() { @@ -36,11 +36,11 @@ export class IndentRangeProvider implements RangeProvider { // public only for testing export class RangesCollector { - private _startIndexes: number[]; - private _endIndexes: number[]; - private _indentOccurrences: number[]; + private readonly _startIndexes: number[]; + private readonly _endIndexes: number[]; + private readonly _indentOccurrences: number[]; private _length: number; - private _foldingRangesLimit: number; + private readonly _foldingRangesLimit: number; constructor(foldingRangesLimit: number) { this._startIndexes = []; diff --git a/src/vs/editor/contrib/folding/intializingRangeProvider.ts b/src/vs/editor/contrib/folding/intializingRangeProvider.ts index 35e4703a853..754ac39f048 100644 --- a/src/vs/editor/contrib/folding/intializingRangeProvider.ts +++ b/src/vs/editor/contrib/folding/intializingRangeProvider.ts @@ -17,7 +17,7 @@ export class InitializingRangeProvider implements RangeProvider { private decorationIds: string[] | undefined; private timeout: any; - constructor(private editorModel: ITextModel, initialRanges: ILineRange[], onTimeout: () => void, timeoutTime: number) { + constructor(private readonly editorModel: ITextModel, initialRanges: ILineRange[], onTimeout: () => void, timeoutTime: number) { if (initialRanges.length) { let toDecorationRange = (range: ILineRange): IModelDeltaDecoration => { return { diff --git a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts index 745d3896403..4e66801be36 100644 --- a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts +++ b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts @@ -25,7 +25,7 @@ export class SyntaxRangeProvider implements RangeProvider { readonly id = ID_SYNTAX_PROVIDER; - constructor(private editorModel: ITextModel, private providers: FoldingRangeProvider[], private limit = MAX_FOLDING_REGIONS) { + constructor(private readonly editorModel: ITextModel, private providers: FoldingRangeProvider[], private limit = MAX_FOLDING_REGIONS) { } compute(cancellationToken: CancellationToken): Promise { @@ -69,13 +69,13 @@ function collectSyntaxRanges(providers: FoldingRangeProvider[], model: ITextMode } export class RangesCollector { - private _startIndexes: number[]; - private _endIndexes: number[]; - private _nestingLevels: number[]; - private _nestingLevelCounts: number[]; - private _types: Array; + private readonly _startIndexes: number[]; + private readonly _endIndexes: number[]; + private readonly _nestingLevels: number[]; + private readonly _nestingLevelCounts: number[]; + private readonly _types: Array; private _length: number; - private _foldingRangesLimit: number; + private readonly _foldingRangesLimit: number; constructor(foldingRangesLimit: number) { this._startIndexes = []; diff --git a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts index 339cc8c9076..f62e4b125d4 100644 --- a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts +++ b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts @@ -31,7 +31,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC private static readonly ID = 'editor.contrib.gotodefinitionwithmouse'; static MAX_SOURCE_PREVIEW_LINES = 8; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private toUnhook: IDisposable[]; private decorations: string[]; private currentWordUnderMouse: IWordAtPosition | null; diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index 8b9cc09fd3c..27fb71091ed 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -29,7 +29,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; class MarkerModel { - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _markers: IMarker[]; private _nextIdx: number; private _toUnbind: IDisposable[]; @@ -202,10 +202,10 @@ export class MarkerController implements editorCommon.IEditorContribution { return editor.getContribution(MarkerController.ID); } - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _model: MarkerModel | null; private _widget: MarkerNavigationWidget | null; - private _widgetVisible: IContextKey; + private readonly _widgetVisible: IContextKey; private _disposeOnClose: IDisposable[] = []; constructor( @@ -337,9 +337,9 @@ export class MarkerController implements editorCommon.IEditorContribution { class MarkerNavigationAction extends EditorAction { - private _isNext: boolean; + private readonly _isNext: boolean; - private _multiFile: boolean; + private readonly _multiFile: boolean; constructor(next: boolean, multiFile: boolean, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts index f841a39d5e8..2729e4aab8a 100644 --- a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -178,8 +178,8 @@ export class MarkerNavigationWidget extends PeekViewWidget { constructor( editor: ICodeEditor, - private actions: IAction[], - private _themeService: IThemeService + private readonly actions: IAction[], + private readonly _themeService: IThemeService ) { super(editor, { showArrow: true, showFrame: true, isAccessible: true }); this._severity = MarkerSeverity.Warning; diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index 12598460131..8c7f8bd5250 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -35,7 +35,7 @@ export class ModesHoverController implements IEditorContribution { private static readonly ID = 'editor.contrib.hover'; private _toUnhook: IDisposable[]; - private _didChangeConfigurationHandler: IDisposable; + private readonly _didChangeConfigurationHandler: IDisposable; private _contentWidget: ModesContentHoverWidget; private _glyphWidget: ModesGlyphHoverWidget; diff --git a/src/vs/editor/contrib/hover/hoverOperation.ts b/src/vs/editor/contrib/hover/hoverOperation.ts index 59c0b9f4366..46195dbeb5b 100644 --- a/src/vs/editor/contrib/hover/hoverOperation.ts +++ b/src/vs/editor/contrib/hover/hoverOperation.ts @@ -47,19 +47,19 @@ export const enum HoverStartMode { export class HoverOperation { - private _computer: IHoverComputer; + private readonly _computer: IHoverComputer; private _state: ComputeHoverOperationState; private _hoverTime: number; - private _firstWaitScheduler: RunOnceScheduler; - private _secondWaitScheduler: RunOnceScheduler; - private _loadingMessageScheduler: RunOnceScheduler; + private readonly _firstWaitScheduler: RunOnceScheduler; + private readonly _secondWaitScheduler: RunOnceScheduler; + private readonly _loadingMessageScheduler: RunOnceScheduler; private _asyncComputationPromise: CancelablePromise | null; private _asyncComputationPromiseDone: boolean; - private _completeCallback: (r: Result) => void; - private _errorCallback: ((err: any) => void) | null | undefined; - private _progressCallback: (progress: any) => void; + private readonly _completeCallback: (r: Result) => void; + private readonly _errorCallback: ((err: any) => void) | null | undefined; + private readonly _progressCallback: (progress: any) => void; constructor(computer: IHoverComputer, success: (r: Result) => void, error: ((err: any) => void) | null | undefined, progress: (progress: any) => void, hoverTime: number) { this._computer = computer; diff --git a/src/vs/editor/contrib/hover/hoverWidgets.ts b/src/vs/editor/contrib/hover/hoverWidgets.ts index 845999b7bf0..71452506714 100644 --- a/src/vs/editor/contrib/hover/hoverWidgets.ts +++ b/src/vs/editor/contrib/hover/hoverWidgets.ts @@ -16,15 +16,15 @@ import { Range } from 'vs/editor/common/core/range'; export class ContentHoverWidget extends Widget implements editorBrowser.IContentWidget { - private _id: string; + private readonly _id: string; protected _editor: editorBrowser.ICodeEditor; private _isVisible: boolean; - private _containerDomNode: HTMLElement; - private _domNode: HTMLElement; + private readonly _containerDomNode: HTMLElement; + private readonly _domNode: HTMLElement; protected _showAtPosition: Position | null; protected _showAtRange: Range | null; private _stoleFocus: boolean; - private scrollbar: DomScrollableElement; + private readonly scrollbar: DomScrollableElement; private disposables: IDisposable[] = []; // Editor.IContentWidget.allowEditorOverflow @@ -164,10 +164,10 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWidget { - private _id: string; + private readonly _id: string; protected _editor: editorBrowser.ICodeEditor; private _isVisible: boolean; - private _domNode: HTMLElement; + private readonly _domNode: HTMLElement; protected _showAtLineNumber: number; constructor(id: string, editor: editorBrowser.ICodeEditor) { diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 671da624c7b..d0f32f542eb 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -64,13 +64,13 @@ type HoverPart = MarkdownHover | ColorHover | MarkerHover; class ModesContentComputer implements IHoverComputer { - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _result: HoverPart[]; private _range: Range | null; constructor( editor: ICodeEditor, - private _markerDecorationsService: IMarkerDecorationsService + private readonly _markerDecorationsService: IMarkerDecorationsService ) { this._editor = editor; this._range = null; @@ -202,8 +202,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget { private _messages: HoverPart[]; private _lastRange: Range | null; - private _computer: ModesContentComputer; - private _hoverOperation: HoverOperation; + private readonly _computer: ModesContentComputer; + private readonly _hoverOperation: HoverOperation; private _highlightDecorations: string[]; private _isChangingDecorations: boolean; private _shouldFocus: boolean; diff --git a/src/vs/editor/contrib/hover/modesGlyphHover.ts b/src/vs/editor/contrib/hover/modesGlyphHover.ts index b5d3da484e9..27af478ad79 100644 --- a/src/vs/editor/contrib/hover/modesGlyphHover.ts +++ b/src/vs/editor/contrib/hover/modesGlyphHover.ts @@ -19,7 +19,7 @@ export interface IHoverMessage { class MarginComputer implements IHoverComputer { - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _lineNumber: number; private _result: IHoverMessage[]; @@ -91,9 +91,9 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget { private _messages: IHoverMessage[]; private _lastLineNumber: number; - private _markdownRenderer: MarkdownRenderer; - private _computer: MarginComputer; - private _hoverOperation: HoverOperation; + private readonly _markdownRenderer: MarkdownRenderer; + private readonly _computer: MarginComputer; + private readonly _hoverOperation: HoverOperation; private _renderDisposeables: IDisposable[]; constructor( diff --git a/src/vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts b/src/vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts index f092044a68c..a64be8e0109 100644 --- a/src/vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts +++ b/src/vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts @@ -10,9 +10,9 @@ import { ITextModel } from 'vs/editor/common/model'; export class InPlaceReplaceCommand implements editorCommon.ICommand { - private _editRange: Range; - private _originalSelection: Selection; - private _text: string; + private readonly _editRange: Range; + private readonly _originalSelection: Selection; + private readonly _text: string; constructor(editRange: Range, originalSelection: Selection, text: string) { this._editRange = editRange; diff --git a/src/vs/editor/contrib/indentation/indentation.ts b/src/vs/editor/contrib/indentation/indentation.ts index 826f53ed2d4..54edce87b07 100644 --- a/src/vs/editor/contrib/indentation/indentation.ts +++ b/src/vs/editor/contrib/indentation/indentation.ts @@ -205,7 +205,7 @@ export class IndentationToTabsAction extends EditorAction { export class ChangeIndentationSizeAction extends EditorAction { - constructor(private insertSpaces: boolean, opts: IActionOptions) { + constructor(private readonly insertSpaces: boolean, opts: IActionOptions) { super(opts); } @@ -375,9 +375,9 @@ export class ReindentSelectedLinesAction extends EditorAction { export class AutoIndentOnPasteCommand implements ICommand { - private _edits: { range: IRange; text: string; eol?: EndOfLineSequence; }[]; + private readonly _edits: { range: IRange; text: string; eol?: EndOfLineSequence; }[]; - private _initialSelection: Selection; + private readonly _initialSelection: Selection; private _selectionId: string; constructor(edits: TextEdit[], initialSelection: Selection) { @@ -422,7 +422,7 @@ export class AutoIndentOnPasteCommand implements ICommand { export class AutoIndentOnPaste implements IEditorContribution { private static readonly ID = 'editor.contrib.autoIndentOnPaste'; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private callOnDispose: IDisposable[]; private callOnModel: IDisposable[]; @@ -653,7 +653,7 @@ export class IndentationToSpacesCommand implements ICommand { private selectionId: string; - constructor(private selection: Selection, private tabSize: number) { } + constructor(private readonly selection: Selection, private tabSize: number) { } public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { this.selectionId = builder.trackSelection(this.selection); @@ -669,7 +669,7 @@ export class IndentationToTabsCommand implements ICommand { private selectionId: string; - constructor(private selection: Selection, private tabSize: number) { } + constructor(private readonly selection: Selection, private tabSize: number) { } public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { this.selectionId = builder.trackSelection(this.selection); diff --git a/src/vs/editor/contrib/linesOperations/copyLinesCommand.ts b/src/vs/editor/contrib/linesOperations/copyLinesCommand.ts index 37f4fb6381c..799b61088f2 100644 --- a/src/vs/editor/contrib/linesOperations/copyLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/copyLinesCommand.ts @@ -10,8 +10,8 @@ import { ITextModel } from 'vs/editor/common/model'; export class CopyLinesCommand implements editorCommon.ICommand { - private _selection: Selection; - private _isCopyingDown: boolean; + private readonly _selection: Selection; + private readonly _isCopyingDown: boolean; private _selectionDirection: SelectionDirection; private _selectionId: string; diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index d1559b13f0c..ffba57fea6a 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -28,7 +28,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis abstract class AbstractCopyLinesAction extends EditorAction { - private down: boolean; + private readonly down: boolean; constructor(down: boolean, opts: IActionOptions) { super(opts); @@ -100,7 +100,7 @@ class CopyLinesDownAction extends AbstractCopyLinesAction { abstract class AbstractMoveLinesAction extends EditorAction { - private down: boolean; + private readonly down: boolean; constructor(down: boolean, opts: IActionOptions) { super(opts); @@ -170,7 +170,7 @@ class MoveLinesDownAction extends AbstractMoveLinesAction { } export abstract class AbstractSortLinesAction extends EditorAction { - private descending: boolean; + private readonly descending: boolean; constructor(descending: boolean, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/linesOperations/moveLinesCommand.ts b/src/vs/editor/contrib/linesOperations/moveLinesCommand.ts index d237c21621b..839dee48043 100644 --- a/src/vs/editor/contrib/linesOperations/moveLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/moveLinesCommand.ts @@ -16,9 +16,9 @@ import * as indentUtils from 'vs/editor/contrib/indentation/indentUtils'; export class MoveLinesCommand implements ICommand { - private _selection: Selection; - private _isMovingDown: boolean; - private _autoIndent: boolean; + private readonly _selection: Selection; + private readonly _isMovingDown: boolean; + private readonly _autoIndent: boolean; private _selectionId: string; private _moveEndPositionDown: boolean; diff --git a/src/vs/editor/contrib/linesOperations/sortLinesCommand.ts b/src/vs/editor/contrib/linesOperations/sortLinesCommand.ts index 779062027c4..304084db5f2 100644 --- a/src/vs/editor/contrib/linesOperations/sortLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/sortLinesCommand.ts @@ -11,9 +11,9 @@ import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/mod export class SortLinesCommand implements editorCommon.ICommand { - private selection: Selection; + private readonly selection: Selection; private selectionId: string; - private descending: boolean; + private readonly descending: boolean; constructor(selection: Selection, descending: boolean) { this.selection = selection; diff --git a/src/vs/editor/contrib/links/getLinks.ts b/src/vs/editor/contrib/links/getLinks.ts index 933fd3f3121..91aac6c28a2 100644 --- a/src/vs/editor/contrib/links/getLinks.ts +++ b/src/vs/editor/contrib/links/getLinks.ts @@ -15,7 +15,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; export class Link implements ILink { private _link: ILink; - private _provider: LinkProvider; + private readonly _provider: LinkProvider; constructor(link: ILink, provider: LinkProvider) { this._link = link; diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 972a60cd4c5..b3c5f8d0cb6 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -153,14 +153,14 @@ class LinkDetector implements editorCommon.IEditorContribution { static RECOMPUTE_TIME = 1000; // ms - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private enabled: boolean; private listenersToRemove: IDisposable[]; - private timeout: async.TimeoutTimer; + private readonly timeout: async.TimeoutTimer; private computePromise: async.CancelablePromise | null; private activeLinkDecorationId: string | null; - private openerService: IOpenerService; - private notificationService: INotificationService; + private readonly openerService: IOpenerService; + private readonly notificationService: INotificationService; private currentOccurrences: { [decorationId: string]: LinkOccurrence; }; constructor( diff --git a/src/vs/editor/contrib/message/messageController.ts b/src/vs/editor/contrib/message/messageController.ts index 9ec3dfaad90..e522a12f8dc 100644 --- a/src/vs/editor/contrib/message/messageController.ts +++ b/src/vs/editor/contrib/message/messageController.ts @@ -33,8 +33,8 @@ export class MessageController extends Disposable implements editorCommon.IEdito return MessageController._id; } - private _editor: ICodeEditor; - private _visible: IContextKey; + private readonly _editor: ICodeEditor; + private readonly _visible: IContextKey; private _messageWidget: MessageWidget; private _messageListeners: IDisposable[] = []; @@ -125,9 +125,9 @@ class MessageWidget implements IContentWidget { readonly allowEditorOverflow = true; readonly suppressMouseDown = false; - private _editor: ICodeEditor; - private _position: IPosition; - private _domNode: HTMLDivElement; + private readonly _editor: ICodeEditor; + private readonly _position: IPosition; + private readonly _domNode: HTMLDivElement; static fadeOut(messageWidget: MessageWidget): IDisposable { let handle: any; diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index da531f7a83d..330d6811342 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -802,10 +802,10 @@ class SelectionHighlighterState { export class SelectionHighlighter extends Disposable implements IEditorContribution { private static readonly ID = 'editor.contrib.selectionHighlighter'; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private _isEnabled: boolean; private decorations: string[]; - private updateSoon: RunOnceScheduler; + private readonly updateSoon: RunOnceScheduler; private state: SelectionHighlighterState | null; constructor(editor: ICodeEditor) { diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts b/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts index 3635b5c8948..cc34a7ec265 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts @@ -45,13 +45,13 @@ export class ParameterHintsModel extends Disposable { private readonly _onChangedHints = this._register(new Emitter()); public readonly onChangedHints = this._onChangedHints.event; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private enabled: boolean; private state: ParameterHintState.State = ParameterHintState.Default; private triggerChars = new CharacterSet(); private retriggerChars = new CharacterSet(); - private throttledDelayer: Delayer; + private readonly throttledDelayer: Delayer; private provideSignatureHelpRequest?: CancelablePromise; private triggerId = 0; diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index d20abceae6a..5c365daebac 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -47,7 +47,7 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { allowEditorOverflow = true; constructor( - private editor: ICodeEditor, + private readonly editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService, @IOpenerService openerService: IOpenerService, @IModeService modeService: IModeService, diff --git a/src/vs/editor/contrib/referenceSearch/referencesController.ts b/src/vs/editor/contrib/referenceSearch/referencesController.ts index 6cd7323f6c6..363e8c2cf0f 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesController.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesController.ts @@ -32,21 +32,21 @@ export abstract class ReferencesController implements editorCommon.IEditorContri private static readonly ID = 'editor.contrib.referencesController'; - private _editor: ICodeEditor; + private readonly _editor: ICodeEditor; private _widget: ReferenceWidget | null; private _model: ReferencesModel | null; private _requestIdPool = 0; private _disposables: IDisposable[] = []; private _ignoreModelChangeEvent = false; - private _referenceSearchVisible: IContextKey; + private readonly _referenceSearchVisible: IContextKey; public static get(editor: ICodeEditor): ReferencesController { return editor.getContribution(ReferencesController.ID); } public constructor( - private _defaultTreeKeyboardSupport: boolean, + private readonly _defaultTreeKeyboardSupport: boolean, editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService, @ICodeEditorService private readonly _editorService: ICodeEditorService, diff --git a/src/vs/editor/contrib/referenceSearch/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/referencesModel.ts index 4243491a8b4..780e1421cf3 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesModel.ts @@ -89,7 +89,7 @@ export class FileReferences implements IDisposable { private _resolved: boolean; private _loadFailure: any; - constructor(private readonly _parent: ReferencesModel, private _uri: URI) { + constructor(private readonly _parent: ReferencesModel, private readonly _uri: URI) { this._children = []; } diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index b24a90cc31f..ac1323fe028 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -244,10 +244,10 @@ class SuggestionDetails { constructor( container: HTMLElement, - private widget: SuggestWidget, - private editor: ICodeEditor, - private markdownRenderer: MarkdownRenderer, - private triggerKeybindingLabel: string + private readonly widget: SuggestWidget, + private readonly editor: ICodeEditor, + private readonly markdownRenderer: MarkdownRenderer, + private readonly triggerKeybindingLabel: string ) { this.disposables = []; @@ -417,8 +417,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate; private listHeight: number; - private suggestWidgetVisible: IContextKey; - private suggestWidgetMultipleSuggestions: IContextKey; + private readonly suggestWidgetVisible: IContextKey; + private readonly suggestWidgetMultipleSuggestions: IContextKey; private readonly editorBlurTimeout = new TimeoutTimer(); private readonly showTimeout = new TimeoutTimer(); @@ -437,7 +437,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate; + private readonly _hasWordHighlights: IContextKey; private _ignorePositionChangeEvent: boolean; constructor(editor: IActiveCodeEditor, contextKeyService: IContextKeyService) { @@ -526,7 +526,7 @@ class WordHighlighterContribution extends Disposable implements editorCommon.IEd class WordHighlightNavigationAction extends EditorAction { - private _isNext: boolean; + private readonly _isNext: boolean; constructor(next: boolean, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts index 23fc9214c5a..8afb01b965e 100644 --- a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts @@ -56,8 +56,8 @@ export class ViewZoneDelegate implements IViewZone { public afterColumn: number; public heightInLines: number; - private _onDomNodeTop: (top: number) => void; - private _onComputedHeight: (height: number) => void; + private readonly _onDomNodeTop: (top: number) => void; + private readonly _onComputedHeight: (height: number) => void; constructor(domNode: HTMLElement, afterLineNumber: number, afterColumn: number, heightInLines: number, onDomNodeTop: (top: number) => void, @@ -82,8 +82,8 @@ export class ViewZoneDelegate implements IViewZone { export class OverlayWidgetDelegate implements IOverlayWidget { - private _id: string; - private _domNode: HTMLElement; + private readonly _id: string; + private readonly _domNode: HTMLElement; constructor(id: string, domNode: HTMLElement) { this._id = id; diff --git a/src/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts b/src/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts index cacc646f626..de148460fcd 100644 --- a/src/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts +++ b/src/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts @@ -44,8 +44,8 @@ class AccessibilityHelpController extends Disposable ); } - private _editor: ICodeEditor; - private _widget: AccessibilityHelpWidget; + private readonly _editor: ICodeEditor; + private readonly _widget: AccessibilityHelpWidget; constructor( editor: ICodeEditor, @@ -107,11 +107,11 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { private static readonly WIDTH = 500; private static readonly HEIGHT = 300; - private _editor: ICodeEditor; - private _domNode: FastDomNode; - private _contentDomNode: FastDomNode; + private readonly _editor: ICodeEditor; + private readonly _domNode: FastDomNode; + private readonly _contentDomNode: FastDomNode; private _isVisible: boolean; - private _isVisibleKey: IContextKey; + private readonly _isVisibleKey: IContextKey; constructor( editor: ICodeEditor, diff --git a/src/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts b/src/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts index 722105f2cf7..e48dcba6535 100644 --- a/src/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts +++ b/src/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts @@ -15,7 +15,7 @@ export class IPadShowKeyboard implements IEditorContribution { private static readonly ID = 'editor.contrib.iPadShowKeyboard'; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private widget: ShowKeyboardWidget | null; private toDispose: IDisposable[]; @@ -60,9 +60,9 @@ class ShowKeyboardWidget implements IOverlayWidget { private static readonly ID = 'editor.contrib.ShowKeyboardWidget'; - private editor: ICodeEditor; + private readonly editor: ICodeEditor; - private _domNode: HTMLElement; + private readonly _domNode: HTMLElement; private _toDispose: IDisposable[]; constructor(editor: ICodeEditor) { diff --git a/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts b/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts index 7369afaad96..d81cdd22f70 100644 --- a/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts +++ b/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts @@ -31,8 +31,8 @@ class InspectTokensController extends Disposable implements IEditorContribution return editor.getContribution(InspectTokensController.ID); } - private _editor: ICodeEditor; - private _modeService: IModeService; + private readonly _editor: ICodeEditor; + private readonly _modeService: IModeService; private _widget: InspectTokensWidget | null; constructor( @@ -162,11 +162,11 @@ class InspectTokensWidget extends Disposable implements IContentWidget { // Editor.IContentWidget.allowEditorOverflow public allowEditorOverflow = true; - private _editor: IActiveCodeEditor; - private _modeService: IModeService; - private _tokenizationSupport: ITokenizationSupport; - private _model: ITextModel; - private _domNode: HTMLElement; + private readonly _editor: IActiveCodeEditor; + private readonly _modeService: IModeService; + private readonly _tokenizationSupport: ITokenizationSupport; + private readonly _model: ITextModel; + private readonly _domNode: HTMLElement; constructor( editor: IActiveCodeEditor, diff --git a/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts b/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts index 0a77b555d7d..c8fb32757b4 100644 --- a/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts +++ b/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts @@ -30,7 +30,7 @@ export class QuickOpenController implements editorCommon.IEditorContribution, ID return editor.getContribution(QuickOpenController.ID); } - private editor: ICodeEditor; + private readonly editor: ICodeEditor; private widget: QuickOpenEditorWidget | null; private rangeHighlightDecorationId: string | null; private lastKnownEditorSelection: Selection | null; @@ -148,7 +148,7 @@ export interface IQuickOpenOpts { */ export abstract class BaseEditorQuickOpenAction extends EditorAction { - private _inputAriaLabel: string; + private readonly _inputAriaLabel: string; constructor(inputAriaLabel: string, opts: IActionOptions) { super(opts); diff --git a/src/vs/editor/standalone/browser/quickOpen/gotoLine.ts b/src/vs/editor/standalone/browser/quickOpen/gotoLine.ts index 47cc1ea540d..d2d1269bafa 100644 --- a/src/vs/editor/standalone/browser/quickOpen/gotoLine.ts +++ b/src/vs/editor/standalone/browser/quickOpen/gotoLine.ts @@ -25,9 +25,9 @@ interface ParseResult { } export class GotoLineEntry extends QuickOpenEntry { - private parseResult: ParseResult; - private decorator: IDecorator; - private editor: editorCommon.IEditor; + private readonly parseResult: ParseResult; + private readonly decorator: IDecorator; + private readonly editor: editorCommon.IEditor; constructor(line: string, editor: editorCommon.IEditor, decorator: IDecorator) { super(); diff --git a/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts b/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts index fdbf17a7685..cf910c605d4 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts @@ -19,10 +19,10 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; export class EditorActionCommandEntry extends QuickOpenEntryGroup { - private key: string; - private action: IEditorAction; - private editor: IEditor; - private keyAriaLabel: string; + private readonly key: string; + private readonly action: IEditorAction; + private readonly editor: IEditor; + private readonly keyAriaLabel: string; constructor(key: string, keyAriaLabel: string, highlights: IHighlight[], action: IEditorAction, editor: IEditor) { super(); diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts index 859e8cca21b..d97591fd2ec 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts @@ -21,8 +21,8 @@ export class QuickOpenEditorWidget implements IOverlayWidget { private static readonly ID = 'editor.contrib.quickOpenEditorWidget'; - private codeEditor: ICodeEditor; - private themeService: IThemeService; + private readonly codeEditor: ICodeEditor; + private readonly themeService: IThemeService; private visible: boolean; private quickOpenWidget: QuickOpenWidget; private domNode: HTMLElement; diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index 7a303f61636..443f884f25a 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -24,12 +24,12 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis let SCOPE_PREFIX = ':'; export class SymbolEntry extends QuickOpenEntryGroup { - private name: string; - private type: string; - private description: string | null; - private range: Range; - private editor: ICodeEditor; - private decorator: IDecorator; + private readonly name: string; + private readonly type: string; + private readonly description: string | null; + private readonly range: Range; + private readonly editor: ICodeEditor; + private readonly decorator: IDecorator; constructor(name: string, type: string, description: string | null, range: Range, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator) { super(); diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index ab55ea98971..66f68e5bc26 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -47,7 +47,7 @@ import { ILayoutService, IDimension } from 'vs/platform/layout/browser/layoutSer export class SimpleModel implements IResolvedTextEditorModel { - private model: ITextModel; + private readonly model: ITextModel; private readonly _onDispose: Emitter; constructor(model: ITextModel) { @@ -247,7 +247,7 @@ export class StandaloneCommandService implements ICommandService { _serviceBrand: any; private readonly _instantiationService: IInstantiationService; - private _dynamicCommands: { [id: string]: ICommand; }; + private readonly _dynamicCommands: { [id: string]: ICommand; }; private readonly _onWillExecuteCommand = new Emitter(); public readonly onWillExecuteCommand: Event = this._onWillExecuteCommand.event; @@ -283,7 +283,7 @@ export class StandaloneCommandService implements ICommandService { export class StandaloneKeybindingService extends AbstractKeybindingService { private _cachedResolver: KeybindingResolver | null; - private _dynamicKeybindings: IKeybindingItem[]; + private readonly _dynamicKeybindings: IKeybindingItem[]; constructor( contextKeyService: IContextKeyService, @@ -423,7 +423,7 @@ export class SimpleConfigurationService implements IConfigurationService { private _onDidChangeConfiguration = new Emitter(); public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; - private _configuration: Configuration; + private readonly _configuration: Configuration; constructor() { this._configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel()); @@ -478,7 +478,7 @@ export class SimpleResourceConfigurationService implements ITextResourceConfigur public readonly onDidChangeConfiguration: Event; private readonly _onDidChangeConfigurationEmitter = new Emitter(); - constructor(private configurationService: SimpleConfigurationService) { + constructor(private readonly configurationService: SimpleConfigurationService) { this.configurationService.onDidChangeConfiguration((e) => { this._onDidChangeConfigurationEmitter.fire(e); }); diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index d7c016cae9d..2eced8d0f6b 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -153,7 +153,7 @@ function createAriaDomNode() { */ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandaloneCodeEditor { - private _standaloneKeybindingService: StandaloneKeybindingService; + private readonly _standaloneKeybindingService: StandaloneKeybindingService; constructor( domElement: HTMLElement, @@ -280,7 +280,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon export class StandaloneEditor extends StandaloneCodeEditor implements IStandaloneCodeEditor { - private _contextViewService: ContextViewService; + private readonly _contextViewService: ContextViewService; private readonly _configurationService: IConfigurationService; private _ownsModel: boolean; @@ -358,7 +358,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon export class StandaloneDiffEditor extends DiffEditorWidget implements IStandaloneDiffEditor { - private _contextViewService: ContextViewService; + private readonly _contextViewService: ContextViewService; private readonly _configurationService: IConfigurationService; constructor( diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 1d0568208d0..01f45b769c4 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -57,8 +57,8 @@ export module StaticServices { const _serviceCollection = new ServiceCollection(); export class LazyStaticService { - private _serviceId: ServiceIdentifier; - private _factory: (overrides?: IEditorOverrideServices) => T; + private readonly _serviceId: ServiceIdentifier; + private readonly _factory: (overrides?: IEditorOverrideServices) => T; private _value: T | null; public get id() { return this._serviceId; } @@ -162,8 +162,8 @@ export module StaticServices { export class DynamicStandaloneServices extends Disposable { - private _serviceCollection: ServiceCollection; - private _instantiationService: IInstantiationService; + private readonly _serviceCollection: ServiceCollection; + private readonly _instantiationService: IInstantiationService; constructor(domElement: HTMLElement, overrides: IEditorOverrideServices) { super(); diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 7efa2c38ba7..5e9074577a3 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -26,9 +26,9 @@ class StandaloneTheme implements IStandaloneTheme { public readonly id: string; public readonly themeName: string; - private themeData: IStandaloneThemeData; + private readonly themeData: IStandaloneThemeData; private colors: { [colorId: string]: Color } | null; - private defaultColors: { [colorId: string]: Color | undefined; }; + private readonly defaultColors: { [colorId: string]: Color | undefined; }; private _tokenTheme: TokenTheme | null; constructor(name: string, standaloneThemeData: IStandaloneThemeData) { @@ -159,12 +159,12 @@ export class StandaloneThemeServiceImpl implements IStandaloneThemeService { _serviceBrand: any; - private _knownThemes: Map; - private _styleElement: HTMLStyleElement; + private readonly _knownThemes: Map; + private readonly _styleElement: HTMLStyleElement; private _theme: IStandaloneTheme; private readonly _onThemeChange: Emitter; private readonly _onIconThemeChange: Emitter; - private environment: IEnvironmentService = Object.create(null); + private readonly environment: IEnvironmentService = Object.create(null); constructor() { this._onThemeChange = new Emitter(); diff --git a/src/vs/editor/standalone/common/monarch/monarchLexer.ts b/src/vs/editor/standalone/common/monarch/monarchLexer.ts index 6d8b55352ab..2567c561f7c 100644 --- a/src/vs/editor/standalone/common/monarch/monarchLexer.ts +++ b/src/vs/editor/standalone/common/monarch/monarchLexer.ts @@ -289,8 +289,8 @@ class MonarchClassicTokensCollector implements IMonarchTokensCollector { class MonarchModernTokensCollector implements IMonarchTokensCollector { - private _modeService: IModeService; - private _theme: TokenTheme; + private readonly _modeService: IModeService; + private readonly _theme: TokenTheme; private _prependTokens: Uint32Array | null; private _tokens: number[]; private _currentLanguageId: modes.LanguageId; @@ -382,9 +382,9 @@ export class MonarchTokenizer implements modes.ITokenizationSupport { private readonly _standaloneThemeService: IStandaloneThemeService; private readonly _modeId: string; private readonly _lexer: monarchCommon.ILexer; - private _embeddedModes: { [modeId: string]: boolean; }; + private readonly _embeddedModes: { [modeId: string]: boolean; }; public embeddedLoaded: Promise; - private _tokenizationRegistryListener: IDisposable; + private readonly _tokenizationRegistryListener: IDisposable; constructor(modeService: IModeService, standaloneThemeService: IStandaloneThemeService, modeId: string, lexer: monarchCommon.ILexer) { this._modeService = modeService; diff --git a/src/vs/editor/test/browser/controller/imeTester.ts b/src/vs/editor/test/browser/controller/imeTester.ts index 4ea8935cd20..1dd06565c23 100644 --- a/src/vs/editor/test/browser/controller/imeTester.ts +++ b/src/vs/editor/test/browser/controller/imeTester.ts @@ -44,7 +44,7 @@ class SingleLineTestModel implements ISimpleModel { class TestView { - private _model: SingleLineTestModel; + private readonly _model: SingleLineTestModel; constructor(model: SingleLineTestModel) { this._model = model; diff --git a/src/vs/editor/test/common/mocks/mockMode.ts b/src/vs/editor/test/common/mocks/mockMode.ts index bf24cc35ceb..703a760c7ad 100644 --- a/src/vs/editor/test/common/mocks/mockMode.ts +++ b/src/vs/editor/test/common/mocks/mockMode.ts @@ -9,7 +9,7 @@ import { IMode, LanguageIdentifier } from 'vs/editor/common/modes'; import { ILanguageSelection } from 'vs/editor/common/services/modeService'; export class MockMode extends Disposable implements IMode { - private _languageIdentifier: LanguageIdentifier; + private readonly _languageIdentifier: LanguageIdentifier; constructor(languageIdentifier: LanguageIdentifier) { super();