From 37f4030344ee2332ed75286aeec888a5bd2f9ae9 Mon Sep 17 00:00:00 2001 From: Tan Jay Jun Date: Wed, 25 Oct 2017 19:39:20 +0800 Subject: [PATCH 01/32] Add character countdown to commit message input --- .../parts/scm/electron-browser/scmViewlet.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 4530cff6727..dfa90ace492 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -45,7 +45,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Command } from 'vs/editor/common/modes'; @@ -753,7 +753,21 @@ export class RepositoryPanel extends ViewletPanel { this.inputBox.setPlaceHolder(placeholder); }; - this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { flexibleHeight: true }); + this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { + flexibleHeight: true, + validationOptions: { + validation: (text: string) => { + const charactersLeft = 72 - text.length; + if (text.length > 72) { + return { content: `${charactersLeft} characters left`, type: MessageType.ERROR }; + } else if (text.length > 55) { + return { content: `${charactersLeft} characters left`, type: MessageType.WARNING }; + } else { + return { content: `${charactersLeft} characters left`, type: MessageType.INFO }; + } + } + } + }); this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService)); this.disposables.push(this.inputBox); From c407635fdfc3efc515760f31cbaafe9798505624 Mon Sep 17 00:00:00 2001 From: Tan Jay Jun Date: Sat, 11 Nov 2017 21:09:54 +0800 Subject: [PATCH 02/32] Add warningLength to SourceControlInputBox --- extensions/git/src/repository.ts | 1 + src/vs/vscode.d.ts | 5 +++ .../api/electron-browser/mainThreadSCM.ts | 10 +++++ src/vs/workbench/api/node/extHost.protocol.ts | 1 + src/vs/workbench/api/node/extHostSCM.ts | 13 ++++++- .../parts/scm/electron-browser/scmViewlet.ts | 38 ++++++++++++------- src/vs/workbench/services/scm/common/scm.ts | 2 + .../services/scm/common/scmService.ts | 12 +++++- 8 files changed, 67 insertions(+), 15 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index c400a818d9d..3bbe3bdd68e 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -484,6 +484,7 @@ export class Repository implements Disposable { this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)"); this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.quickDiffProvider = this; + this._sourceControl.inputBox.warningLength = 72; this.disposables.push(this._sourceControl); this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes")); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index b02773f70b9..31988396618 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5782,6 +5782,11 @@ declare module 'vscode' { * A string to show as place holder in the input box to guide the user. */ placeholder: string; + + /** + * The warning threshold for commit messages. + */ + warningLength: number | undefined; } interface QuickDiffProvider { diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 88c6377b3c4..7e728e798bd 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -391,4 +391,14 @@ export class MainThreadSCM implements MainThreadSCMShape { repository.input.placeholder = placeholder; } + + $setWarningLength(sourceControlHandle: number, warningLength: number): void { + const repository = this._repositories[sourceControlHandle]; + + if (!repository) { + return; + } + + repository.input.warningLength = warningLength; + } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index cb65d9c5c87..16e43487787 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -410,6 +410,7 @@ export interface MainThreadSCMShape extends IDisposable { $setInputBoxValue(sourceControlHandle: number, value: string): void; $setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void; + $setWarningLength(sourceControlHandle: number, warningLength: number): void; } export type DebugSessionUUID = string; diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 9444ef00744..2f8ea94d5b6 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -110,7 +110,7 @@ function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.S return result; } -export class ExtHostSCMInputBox { +export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { private _value: string = ''; @@ -140,6 +140,17 @@ export class ExtHostSCMInputBox { this._placeholder = placeholder; } + private _warningLength: number | undefined; + + get warningLength(): number | undefined { + return this._warningLength; + } + + set warningLength(warningLength: number) { + this._proxy.$setWarningLength(this._sourceControlHandle, warningLength); + this._warningLength = warningLength; + } + constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) { // noop } diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index dfa90ace492..982d059e337 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -45,7 +45,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; -import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; +import { IMessage, InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Command } from 'vs/editor/common/modes'; @@ -753,20 +753,32 @@ export class RepositoryPanel extends ViewletPanel { this.inputBox.setPlaceHolder(placeholder); }; + const validation = (text: string): IMessage => { + const warningLength = this.repository.input.warningLength; + if (warningLength === undefined) { + return { + content: localize('commitMessageInfo', "{0} characters", text.length), + type: MessageType.INFO + }; + } + + const charactersLeft = warningLength - text.length; + if (charactersLeft > 0) { + return { + content: localize('commitMessageCountdown', "{0} characters left", text.length), + type: MessageType.INFO + }; + } else { + return { + content: localize('commitMessageWarning', "{0} characters over", text.length), + type: MessageType.WARNING + }; + } + }; + this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { flexibleHeight: true, - validationOptions: { - validation: (text: string) => { - const charactersLeft = 72 - text.length; - if (text.length > 72) { - return { content: `${charactersLeft} characters left`, type: MessageType.ERROR }; - } else if (text.length > 55) { - return { content: `${charactersLeft} characters left`, type: MessageType.WARNING }; - } else { - return { content: `${charactersLeft} characters left`, type: MessageType.INFO }; - } - } - } + validationOptions: { validation: validation } }); this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService)); this.disposables.push(this.inputBox); diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index 78c1252f599..b10ab4dc7cc 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -74,6 +74,8 @@ export interface ISCMInput { placeholder: string; readonly onDidChangePlaceholder: Event; + + warningLength: number | undefined; } export interface ISCMRepository extends IDisposable { diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index db569fc7c57..a16e88a7436 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -39,6 +39,16 @@ class SCMInput implements ISCMInput { private _onDidChangePlaceholder = new Emitter(); get onDidChangePlaceholder(): Event { return this._onDidChangePlaceholder.event; } + + private _warningLength: number | undefined; + + get warningLength(): number | undefined { + return this._warningLength; + } + + set warningLength(warningLength: number) { + this._warningLength = warningLength; + } } class SCMRepository implements ISCMRepository { @@ -106,4 +116,4 @@ export class SCMService implements ISCMService { return repository; } -} \ No newline at end of file +} From 0d8a59bbc4b5e1bd9e3f3d6c2b4893b0e586095a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Dec 2017 17:13:03 +0100 Subject: [PATCH 03/32] Fix #37084 --- .../browser/parts/views/viewsViewlet.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 0238302847f..7bc93ba609f 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -580,16 +580,22 @@ export class ViewsViewlet extends PanelViewlet { if (this.length > 1) { return false; } - // Check in cache so that view do not jump. See #29609 - if (ViewLocation.getContributedViewLocation(this.location.id) && !this.areExtensionsReady) { + + if (ViewLocation.getContributedViewLocation(this.location.id)) { let visibleViewsCount = 0; - this.viewsStates.forEach((viewState, id) => { - if (!viewState.isHidden) { - visibleViewsCount++; - } - }); + if (this.areExtensionsReady) { + visibleViewsCount = this.getViewDescriptorsFromRegistry().reduce((visibleViewsCount, v) => visibleViewsCount + (this.canBeVisible(v) ? 1 : 0), 0); + } else { + // Check in cache so that view do not jump. See #29609 + this.viewsStates.forEach((viewState, id) => { + if (!viewState.isHidden) { + visibleViewsCount++; + } + }); + } return visibleViewsCount === 1; } + return super.isSingleView(); } From a58e51c10c097d1965479db41624cb8444344654 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Dec 2017 08:32:59 -0800 Subject: [PATCH 04/32] Dynamically import xterm.js This should save 30-40ms on start up Part of #30685 --- .../electron-browser/terminalInstance.ts | 210 +++++++++--------- .../electron-browser/terminalInstance.test.ts | 3 +- 2 files changed, 112 insertions(+), 101 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f5886a2d038..9a550a732f0 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -39,10 +39,7 @@ import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; -// Enable search functionality in xterm.js instance -XTermTerminal.loadAddon('search'); -// Enable the winpty compatibility addon which will simulate wraparound mode -XTermTerminal.loadAddon('winptyCompat'); +let Terminal: typeof XTermTerminal; enum ProcessState { // The process has not been initialized yet. @@ -97,6 +94,7 @@ export class TerminalInstance implements ITerminalInstance { private _initialCwd: string; private _windowsShellHelper: WindowsShellHelper; private _onLineDataListeners: ((lineData: string) => void)[]; + private _xtermReadyPromise: TPromise; private _widgetManager: TerminalWidgetManager; private _linkHandler: TerminalLinkHandler; @@ -150,7 +148,6 @@ export class TerminalInstance implements ITerminalInstance { this._initDimensions(); this._createProcess(); - this._createXterm(); if (platform.isWindows) { this._processReady.then(() => { @@ -160,10 +157,13 @@ export class TerminalInstance implements ITerminalInstance { }); } - // Only attach xterm.js to the DOM if the terminal panel has been opened before. - if (_container) { - this.attachToElement(_container); - } + this._xtermReadyPromise = this._createXterm(); + this._xtermReadyPromise.then(() => { + // Only attach xterm.js to the DOM if the terminal panel has been opened before. + if (_container) { + this.attachToElement(_container); + } + }); } public addDisposable(disposable: lifecycle.IDisposable): void { @@ -248,9 +248,17 @@ export class TerminalInstance implements ITerminalInstance { /** * Create xterm.js instance and attach data listeners. */ - protected _createXterm(): void { + protected async _createXterm(): TPromise { + if (!Terminal) { + console.log('load xterm now'); + Terminal = (await import('xterm')).Terminal; + // Enable search functionality in xterm.js instance + Terminal.loadAddon('search'); + // Enable the winpty compatibility addon which will simulate wraparound mode + Terminal.loadAddon('winptyCompat'); + } const font = this._configHelper.getFont(true); - this._xterm = new XTermTerminal({ + this._xterm = new Terminal({ scrollback: this._configHelper.config.scrollback, theme: this._getXtermTheme(), fontFamily: font.fontFamily, @@ -284,100 +292,102 @@ export class TerminalInstance implements ITerminalInstance { } public attachToElement(container: HTMLElement): void { - if (this._wrapperElement) { - throw new Error('The terminal instance has already been attached to a container'); - } - - this._container = container; - this._wrapperElement = document.createElement('div'); - dom.addClass(this._wrapperElement, 'terminal-wrapper'); - this._xtermElement = document.createElement('div'); - - // Attach the xterm object to the DOM, exposing it to the smoke tests - (this._wrapperElement).xterm = this._xterm; - - this._xterm.open(this._xtermElement); - this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => { - // Disable all input if the terminal is exiting - if (this._isExiting) { - return false; + this._xtermReadyPromise.then(() => { + if (this._wrapperElement) { + throw new Error('The terminal instance has already been attached to a container'); } - // Skip processing by xterm.js of keyboard events that resolve to commands described - // within commandsToSkipShell - const standardKeyboardEvent = new StandardKeyboardEvent(event); - const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); - if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { - event.preventDefault(); - return false; - } + this._container = container; + this._wrapperElement = document.createElement('div'); + dom.addClass(this._wrapperElement, 'terminal-wrapper'); + this._xtermElement = document.createElement('div'); - // If tab focus mode is on, tab is not passed to the terminal - if (TabFocus.getTabFocusMode() && event.keyCode === 9) { - return false; - } + // Attach the xterm object to the DOM, exposing it to the smoke tests + (this._wrapperElement).xterm = this._xterm; - return undefined; + this._xterm.open(this._xtermElement); + this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => { + // Disable all input if the terminal is exiting + if (this._isExiting) { + return false; + } + + // Skip processing by xterm.js of keyboard events that resolve to commands described + // within commandsToSkipShell + const standardKeyboardEvent = new StandardKeyboardEvent(event); + const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); + if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { + event.preventDefault(); + return false; + } + + // If tab focus mode is on, tab is not passed to the terminal + if (TabFocus.getTabFocusMode() && event.keyCode === 9) { + return false; + } + + return undefined; + }); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => { + // Wait until mouseup has propagated through the DOM before + // evaluating the new selection state. + setTimeout(() => this._refreshSelectionContextKey(), 0); + })); + + // xterm.js currently drops selection on keyup as we need to handle this case. + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { + // Wait until keyup has propagated through the DOM before evaluating + // the new selection state. + setTimeout(() => this._refreshSelectionContextKey(), 0); + })); + + const xtermHelper: HTMLElement = this._xterm.element.querySelector('.xterm-helpers'); + const focusTrap: HTMLElement = document.createElement('div'); + focusTrap.setAttribute('tabindex', '0'); + dom.addClass(focusTrap, 'focus-trap'); + this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { + let currentElement = focusTrap; + while (!dom.hasClass(currentElement, 'part')) { + currentElement = currentElement.parentElement; + } + const hidePanelElement = currentElement.querySelector('.hide-panel-action'); + hidePanelElement.focus(); + })); + xtermHelper.insertBefore(focusTrap, this._xterm.textarea); + + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); + this._refreshSelectionContextKey(); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); + this._refreshSelectionContextKey(); + })); + + this._wrapperElement.appendChild(this._xtermElement); + this._widgetManager = new TerminalWidgetManager(this._wrapperElement); + this._linkHandler.setWidgetManager(this._widgetManager); + this._container.appendChild(this._wrapperElement); + + const computedStyle = window.getComputedStyle(this._container); + const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); + const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); + this.layout(new Dimension(width, height)); + this.setVisible(this._isVisible); + this.updateConfig(); + + // If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal + // panel was initialized. + if (this._xterm.getOption('disableStdin')) { + this._attachPressAnyKeyToCloseListener(); + } }); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => { - // Wait until mouseup has propagated through the DOM before - // evaluating the new selection state. - setTimeout(() => this._refreshSelectionContextKey(), 0); - })); - - // xterm.js currently drops selection on keyup as we need to handle this case. - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { - // Wait until keyup has propagated through the DOM before evaluating - // the new selection state. - setTimeout(() => this._refreshSelectionContextKey(), 0); - })); - - const xtermHelper: HTMLElement = this._xterm.element.querySelector('.xterm-helpers'); - const focusTrap: HTMLElement = document.createElement('div'); - focusTrap.setAttribute('tabindex', '0'); - dom.addClass(focusTrap, 'focus-trap'); - this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { - let currentElement = focusTrap; - while (!dom.hasClass(currentElement, 'part')) { - currentElement = currentElement.parentElement; - } - const hidePanelElement = currentElement.querySelector('.hide-panel-action'); - hidePanelElement.focus(); - })); - xtermHelper.insertBefore(focusTrap, this._xterm.textarea); - - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { - this._terminalFocusContextKey.set(true); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { - this._terminalFocusContextKey.reset(); - this._refreshSelectionContextKey(); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { - this._terminalFocusContextKey.set(true); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { - this._terminalFocusContextKey.reset(); - this._refreshSelectionContextKey(); - })); - - this._wrapperElement.appendChild(this._xtermElement); - this._widgetManager = new TerminalWidgetManager(this._wrapperElement); - this._linkHandler.setWidgetManager(this._widgetManager); - this._container.appendChild(this._wrapperElement); - - const computedStyle = window.getComputedStyle(this._container); - const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); - const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); - this.layout(new Dimension(width, height)); - this.setVisible(this._isVisible); - this.updateConfig(); - - // If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal - // panel was initialized. - if (this._xterm.getOption('disableStdin')) { - this._attachPressAnyKeyToCloseListener(); - } } public registerLinkMatcher(regex: RegExp, handler: (url: string) => void, matchIndex?: number, validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void): number { diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts index 608a9e5f8bc..a7f066b25bd 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts @@ -20,6 +20,7 @@ import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybin import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; +import { TPromise } from 'vs/base/common/winjs.base'; class TestTerminalInstance extends TerminalInstance { public _getCwd(shell: IShellLaunchConfig, root: Uri): string { @@ -27,7 +28,7 @@ class TestTerminalInstance extends TerminalInstance { } protected _createProcess(): void { } - protected _createXterm(): void { } + protected _createXterm(): TPromise { return TPromise.as(void 0); } } suite('Workbench - TerminalInstance', () => { From 801e0cadbf16ca7aaa9cd99ff6d54069fc0e2872 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 12 Dec 2017 17:01:07 +0100 Subject: [PATCH 05/32] Simplify OverviewRulerZone (#38418) --- .../editor/browser/widget/diffEditorWidget.ts | 16 ---------- .../editor/common/view/overviewZoneManager.ts | 29 +++++++++--------- .../common/view/overviewZoneManager.test.ts | 30 +++++++++---------- 3 files changed, 29 insertions(+), 46 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 34bfc9c3f15..4aaa31c2ef3 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1619,10 +1619,6 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, color )); @@ -1683,10 +1679,6 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, color )); @@ -1802,10 +1794,6 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, color )); } @@ -1837,10 +1825,6 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, color )); diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index 8bbf6e5e685..d95080db3bc 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -29,30 +29,29 @@ export class ColorZone { export class OverviewRulerZone { _overviewRulerZoneBrand: void; - startLineNumber: number; - endLineNumber: number; - position: OverviewRulerLane; - forceHeight: number; + public readonly startLineNumber: number; + public readonly endLineNumber: number; + public readonly position: OverviewRulerLane; + public readonly forceHeight: number; - private _color: string; - private _darkColor: string; - private _hcColor: string; + private readonly _color: string; + private readonly _darkColor: string; + private readonly _hcColor: string; private _colorZones: ColorZone[]; constructor( - startLineNumber: number, endLineNumber: number, - position: OverviewRulerLane, - forceHeight: number, - color: string, darkColor: string, hcColor: string + startLineNumber: number, + endLineNumber: number, + color: string ) { this.startLineNumber = startLineNumber; this.endLineNumber = endLineNumber; - this.position = position; - this.forceHeight = forceHeight; + this.position = OverviewRulerLane.Full; + this.forceHeight = 0; this._color = color; - this._darkColor = darkColor; - this._hcColor = hcColor; + this._darkColor = color; + this._hcColor = color; this._colorZones = null; } diff --git a/src/vs/editor/test/common/view/overviewZoneManager.test.ts b/src/vs/editor/test/common/view/overviewZoneManager.test.ts index 1cfc1a4a2b1..39928e19adf 100644 --- a/src/vs/editor/test/common/view/overviewZoneManager.test.ts +++ b/src/vs/editor/test/common/view/overviewZoneManager.test.ts @@ -25,15 +25,15 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(1); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 12, but cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(12, 22, 1, OverviewRulerLane.Full), // forced height of 10 + new ColorZone(15, 21, 1, OverviewRulerLane.Full), // new ColorZone(123, 129, 2, OverviewRulerLane.Full), // 120 -> 132 new ColorZone(363, 369, 3, OverviewRulerLane.Full), // 360 -> 372 [360 -> 384] new ColorZone(375, 381, 3, OverviewRulerLane.Full), // 372 -> 384 [360 -> 384] @@ -55,15 +55,15 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(1); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 6, cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(6, 16, 1, OverviewRulerLane.Full), // forced height of 10 + new ColorZone(6, 12, 1, OverviewRulerLane.Full), // new ColorZone(60, 66, 2, OverviewRulerLane.Full), // 60 -> 66 new ColorZone(180, 192, 3, OverviewRulerLane.Full), // 180 -> 192 new ColorZone(294, 300, 4, OverviewRulerLane.Full), // 294 -> 300 @@ -84,15 +84,15 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(2); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 6, cap is at 12 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(12, 32, 1, OverviewRulerLane.Full), // forced height of 10 => forced height of 20 + new ColorZone(12, 24, 1, OverviewRulerLane.Full), // new ColorZone(120, 132, 2, OverviewRulerLane.Full), // 120 -> 132 new ColorZone(360, 384, 3, OverviewRulerLane.Full), // 360 -> 384 new ColorZone(588, 600, 4, OverviewRulerLane.Full), // 588 -> 600 From 80281fde7510c06e1bff7449b049429b884a63a6 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 12 Dec 2017 17:53:28 +0100 Subject: [PATCH 06/32] Simplifications in OverviewZoneManager (#38418) --- src/vs/editor/browser/view/viewImpl.ts | 4 +- .../viewParts/overviewRuler/overviewRuler.ts | 6 +- .../editor/browser/widget/codeEditorWidget.ts | 4 +- .../editor/browser/widget/diffEditorWidget.ts | 4 +- .../editor/common/view/overviewZoneManager.ts | 199 ++++-------------- .../common/view/overviewZoneManager.test.ts | 36 ++-- 6 files changed, 65 insertions(+), 188 deletions(-) diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 08c9c688aed..f67e5b4e7cc 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -472,8 +472,8 @@ export class View extends ViewEventHandler { return this.outgoingEvents; } - public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): OverviewRuler { - return new OverviewRuler(this._context, cssClassName, minimumHeight, maximumHeight); + public createOverviewRuler(cssClassName: string): OverviewRuler { + return new OverviewRuler(this._context, cssClassName); } public change(callback: (changeAccessor: editorBrowser.IViewZoneChangeAccessor) => any): boolean { diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index d5f1311d3b1..ea5e1ba7cfb 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -12,7 +12,6 @@ import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions'; import { OverviewRulerZone, OverviewZoneManager, ColorZone } from 'vs/editor/common/view/overviewZoneManager'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; import { Color } from 'vs/base/common/color'; -import { LIGHT } from 'vs/platform/theme/common/themeService'; import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { @@ -24,7 +23,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { private _zoneManager: OverviewZoneManager; private _background: Color; - constructor(context: ViewContext, cssClassName: string, minimumHeight: number, maximumHeight: number) { + constructor(context: ViewContext, cssClassName: string) { super(); this._context = context; @@ -40,9 +39,6 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._background = null; this._zoneManager = new OverviewZoneManager((lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber)); - this._zoneManager.setMinimumHeight(minimumHeight); - this._zoneManager.setMaximumHeight(maximumHeight); - this._zoneManager.setThemeType(LIGHT); this._zoneManager.setDOMWidth(0); this._zoneManager.setDOMHeight(0); this._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight()); diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 34eb4d6e194..52c8dd723d2 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -157,8 +157,8 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito super.dispose(); } - public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): editorBrowser.IOverviewRuler { - return this._view.createOverviewRuler(cssClassName, minimumHeight, maximumHeight); + public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler { + return this._view.createOverviewRuler(cssClassName); } public getDomNode(): HTMLElement { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 4aaa31c2ef3..2b2a0ab662d 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -361,14 +361,14 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode()); this._originalOverviewRuler.dispose(); } - this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler', 4, Number.MAX_VALUE); + this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler'); this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode()); if (this._modifiedOverviewRuler) { this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode()); this._modifiedOverviewRuler.dispose(); } - this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler', 4, Number.MAX_VALUE); + this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler'); this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode()); this._layoutOverviewRulers(); diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index d95080db3bc..6d200c3c7f5 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -5,7 +5,11 @@ 'use strict'; import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; -import { ThemeType, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService'; +import { ThemeType } from 'vs/platform/theme/common/themeService'; + +const enum Constants { + MINIMUM_HEIGHT = 4 +} export class ColorZone { _colorZoneBrand: void; @@ -15,11 +19,11 @@ export class ColorZone { colorId: number; position: OverviewRulerLane; - constructor(from: number, to: number, colorId: number, position: OverviewRulerLane) { + constructor(from: number, to: number, colorId: number) { this.from = from | 0; this.to = to | 0; this.colorId = colorId | 0; - this.position = position | 0; + this.position = OverviewRulerLane.Full; } } @@ -31,14 +35,9 @@ export class OverviewRulerZone { public readonly startLineNumber: number; public readonly endLineNumber: number; - public readonly position: OverviewRulerLane; - public readonly forceHeight: number; + public readonly color: string; - private readonly _color: string; - private readonly _darkColor: string; - private readonly _hcColor: string; - - private _colorZones: ColorZone[]; + private _colorZone: ColorZone; constructor( startLineNumber: number, @@ -47,55 +46,33 @@ export class OverviewRulerZone { ) { this.startLineNumber = startLineNumber; this.endLineNumber = endLineNumber; - this.position = OverviewRulerLane.Full; - this.forceHeight = 0; - this._color = color; - this._darkColor = color; - this._hcColor = color; - this._colorZones = null; + this.color = color; + this._colorZone = null; } public getColor(themeType: ThemeType): string { - switch (themeType) { - case HIGH_CONTRAST: - return this._hcColor; - case DARK: - return this._darkColor; - } - return this._color; + return this.color; } public compareTo(other: OverviewRulerZone): number { if (this.startLineNumber === other.startLineNumber) { if (this.endLineNumber === other.endLineNumber) { - if (this.forceHeight === other.forceHeight) { - if (this.position === other.position) { - if (this._darkColor === other._darkColor) { - if (this._color === other._color) { - if (this._hcColor === other._hcColor) { - return 0; - } - return this._hcColor < other._hcColor ? -1 : 1; - } - return this._color < other._color ? -1 : 1; - } - return this._darkColor < other._darkColor ? -1 : 1; - } - return this.position - other.position; + if (this.color === other.color) { + return 0; } - return this.forceHeight - other.forceHeight; + return this.color < other.color ? -1 : 1; } return this.endLineNumber - other.endLineNumber; } return this.startLineNumber - other.startLineNumber; } - public setColorZones(colorZones: ColorZone[]): void { - this._colorZones = colorZones; + public setColorZone(colorZone: ColorZone): void { + this._colorZone = colorZone; } - public getColorZones(): ColorZone[] { - return this._colorZones; + public getColorZones(): ColorZone { + return this._colorZone; } } @@ -108,9 +85,6 @@ export class OverviewZoneManager { private _domWidth: number; private _domHeight: number; private _outerHeight: number; - private _maximumHeight: number; - private _minimumHeight: number; - private _themeType: ThemeType; private _pixelRatio: number; private _lastAssignedId: number; @@ -125,9 +99,6 @@ export class OverviewZoneManager { this._domWidth = 0; this._domHeight = 0; this._outerHeight = 0; - this._maximumHeight = 0; - this._minimumHeight = 0; - this._themeType = LIGHT; this._pixelRatio = 1; this._lastAssignedId = 0; @@ -236,97 +207,53 @@ export class OverviewZoneManager { return true; } - public setMaximumHeight(maximumHeight: number): boolean { - if (this._maximumHeight === maximumHeight) { - return false; - } - this._maximumHeight = maximumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setMinimumHeight(minimumHeight: number): boolean { - if (this._minimumHeight === minimumHeight) { - return false; - } - this._minimumHeight = minimumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setThemeType(themeType: ThemeType): boolean { - if (this._themeType === themeType) { - return false; - } - this._themeType = themeType; - this._colorZonesInvalid = true; - return true; - } - public resolveColorZones(): ColorZone[] { const colorZonesInvalid = this._colorZonesInvalid; const lineHeight = Math.floor(this._lineHeight); // @perf const totalHeight = Math.floor(this.getCanvasHeight()); // @perf - const maximumHeight = Math.floor(this._maximumHeight * this._pixelRatio); // @perf - const minimumHeight = Math.floor(this._minimumHeight * this._pixelRatio); // @perf - const themeType = this._themeType; // @perf const outerHeight = Math.floor(this._outerHeight); // @perf const heightRatio = totalHeight / outerHeight; let allColorZones: ColorZone[] = []; for (let i = 0, len = this._zones.length; i < len; i++) { - let zone = this._zones[i]; + const zone = this._zones[i]; if (!colorZonesInvalid) { - let colorZones = zone.getColorZones(); - if (colorZones) { - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); - } + const colorZone = zone.getColorZones(); + if (colorZone) { + allColorZones.push(colorZone); continue; } } - let colorZones: ColorZone[] = []; - if (zone.forceHeight) { - let forcedHeight = Math.floor(zone.forceHeight * this._pixelRatio); + const y1 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.startLineNumber))); + const y2 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight)); - let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); - y1 = Math.floor(y1 * heightRatio); + let ycenter = Math.floor((y1 + y2) / 2); + let halfHeight = (y2 - ycenter); - let y2 = y1 + forcedHeight; - colorZones.push(this.createZone(totalHeight, y1, y2, forcedHeight, forcedHeight, zone.getColor(themeType), zone.position)); - } else { - let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); - let y2 = Math.floor(this._getVerticalOffsetForLine(zone.endLineNumber)) + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - // Figure out if we can render this in one continuous zone - let zoneLineNumbers = zone.endLineNumber - zone.startLineNumber + 1; - let zoneMaximumHeight = zoneLineNumbers * maximumHeight; - - if (y2 - y1 > zoneMaximumHeight) { - // We need to draw one zone per line - for (let lineNumber = zone.startLineNumber; lineNumber <= zone.endLineNumber; lineNumber++) { - y1 = Math.floor(this._getVerticalOffsetForLine(lineNumber)); - y2 = y1 + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, maximumHeight, zone.getColor(themeType), zone.position)); - } - } else { - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, zoneMaximumHeight, zone.getColor(themeType), zone.position)); - } + if (halfHeight < Constants.MINIMUM_HEIGHT / 2) { + halfHeight = Constants.MINIMUM_HEIGHT / 2; } - zone.setColorZones(colorZones); - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); + if (ycenter - halfHeight < 0) { + ycenter = halfHeight; } + if (ycenter + halfHeight > totalHeight) { + ycenter = totalHeight - halfHeight; + } + + const color = zone.color; + let colorId = this._color2Id[color]; + if (!colorId) { + colorId = (++this._lastAssignedId); + this._color2Id[color] = colorId; + this._id2Color[colorId] = color; + } + const colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId); + + zone.setColorZone(colorZone); + allColorZones.push(colorZone); } this._colorZonesInvalid = false; @@ -344,38 +271,4 @@ export class OverviewZoneManager { allColorZones.sort(sortFunc); return allColorZones; } - - public createZone(totalHeight: number, y1: number, y2: number, minimumHeight: number, maximumHeight: number, color: string, position: OverviewRulerLane): ColorZone { - totalHeight = Math.floor(totalHeight); // @perf - y1 = Math.floor(y1); // @perf - y2 = Math.floor(y2); // @perf - minimumHeight = Math.floor(minimumHeight); // @perf - maximumHeight = Math.floor(maximumHeight); // @perf - - let ycenter = Math.floor((y1 + y2) / 2); - let halfHeight = (y2 - ycenter); - - - if (halfHeight > maximumHeight / 2) { - halfHeight = maximumHeight / 2; - } - if (halfHeight < minimumHeight / 2) { - halfHeight = minimumHeight / 2; - } - - if (ycenter - halfHeight < 0) { - ycenter = halfHeight; - } - if (ycenter + halfHeight > totalHeight) { - ycenter = totalHeight - halfHeight; - } - - let colorId = this._color2Id[color]; - if (!colorId) { - colorId = (++this._lastAssignedId); - this._color2Id[color] = colorId; - this._id2Color[colorId] = color; - } - return new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId, position); - } } diff --git a/src/vs/editor/test/common/view/overviewZoneManager.test.ts b/src/vs/editor/test/common/view/overviewZoneManager.test.ts index 39928e19adf..1781b29855b 100644 --- a/src/vs/editor/test/common/view/overviewZoneManager.test.ts +++ b/src/vs/editor/test/common/view/overviewZoneManager.test.ts @@ -5,9 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; import { OverviewZoneManager, ColorZone, OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager'; -import { LIGHT } from 'vs/platform/theme/common/themeService'; suite('Editor View - OverviewZoneManager', () => { @@ -15,9 +13,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(600); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -33,11 +28,10 @@ suite('Editor View - OverviewZoneManager', () => { // one line = 12, but cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(15, 21, 1, OverviewRulerLane.Full), // - new ColorZone(123, 129, 2, OverviewRulerLane.Full), // 120 -> 132 - new ColorZone(363, 369, 3, OverviewRulerLane.Full), // 360 -> 372 [360 -> 384] - new ColorZone(375, 381, 3, OverviewRulerLane.Full), // 372 -> 384 [360 -> 384] - new ColorZone(594, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + new ColorZone(12, 24, 1), // + new ColorZone(120, 132, 2), // 120 -> 132 + new ColorZone(360, 384, 3), // 360 -> 372 [360 -> 384] + new ColorZone(588, 600, 4), // 588 -> 600 ]); }); @@ -45,9 +39,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(300); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -63,10 +54,10 @@ suite('Editor View - OverviewZoneManager', () => { // one line = 6, cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(6, 12, 1, OverviewRulerLane.Full), // - new ColorZone(60, 66, 2, OverviewRulerLane.Full), // 60 -> 66 - new ColorZone(180, 192, 3, OverviewRulerLane.Full), // 180 -> 192 - new ColorZone(294, 300, 4, OverviewRulerLane.Full), // 294 -> 300 + new ColorZone(6, 12, 1), // + new ColorZone(60, 66, 2), // 60 -> 66 + new ColorZone(180, 192, 3), // 180 -> 192 + new ColorZone(294, 300, 4), // 294 -> 300 ]); }); @@ -74,9 +65,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(300); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -92,10 +80,10 @@ suite('Editor View - OverviewZoneManager', () => { // one line = 6, cap is at 12 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(12, 24, 1, OverviewRulerLane.Full), // - new ColorZone(120, 132, 2, OverviewRulerLane.Full), // 120 -> 132 - new ColorZone(360, 384, 3, OverviewRulerLane.Full), // 360 -> 384 - new ColorZone(588, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + new ColorZone(12, 24, 1), // + new ColorZone(120, 132, 2), // 120 -> 132 + new ColorZone(360, 384, 3), // 360 -> 384 + new ColorZone(588, 600, 4), // 588 -> 600 ]); }); }); From 946d872acbe0087466110c7da9d813c135120870 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 12 Dec 2017 17:54:28 +0100 Subject: [PATCH 07/32] input box length warnings introduces scm.inputCounter --- extensions/git/src/repository.ts | 2 +- src/vs/vscode.d.ts | 4 +- .../api/electron-browser/mainThreadSCM.ts | 4 +- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostSCM.ts | 12 ++--- .../scm/electron-browser/scm.contribution.ts | 6 +++ .../parts/scm/electron-browser/scmViewlet.ts | 47 +++++++++++++++---- src/vs/workbench/services/scm/common/scm.ts | 2 +- .../services/scm/common/scmService.ts | 10 +--- 9 files changed, 58 insertions(+), 31 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index abdd8184ffa..4ee58c70fff 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -519,7 +519,7 @@ export class Repository implements Disposable { this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)"); this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.quickDiffProvider = this; - this._sourceControl.inputBox.warningLength = 72; + this._sourceControl.inputBox.lineWarningLength = 72; this.disposables.push(this._sourceControl); this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes")); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 31988396618..86982258339 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5784,9 +5784,9 @@ declare module 'vscode' { placeholder: string; /** - * The warning threshold for commit messages. + * The warning threshold for lines in the input box. */ - warningLength: number | undefined; + lineWarningLength: number | undefined; } interface QuickDiffProvider { diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 7e728e798bd..2541503baa9 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -392,13 +392,13 @@ export class MainThreadSCM implements MainThreadSCMShape { repository.input.placeholder = placeholder; } - $setWarningLength(sourceControlHandle: number, warningLength: number): void { + $setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void { const repository = this._repositories[sourceControlHandle]; if (!repository) { return; } - repository.input.warningLength = warningLength; + repository.input.lineWarningLength = lineWarningLength; } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index d3efe056b8d..f9fd93dfa20 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -410,7 +410,7 @@ export interface MainThreadSCMShape extends IDisposable { $setInputBoxValue(sourceControlHandle: number, value: string): void; $setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void; - $setWarningLength(sourceControlHandle: number, warningLength: number): void; + $setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void; } export type DebugSessionUUID = string; diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 2f8ea94d5b6..37a6b752ab1 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -140,15 +140,15 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { this._placeholder = placeholder; } - private _warningLength: number | undefined; + private _lineWarningLength: number | undefined; - get warningLength(): number | undefined { - return this._warningLength; + get lineWarningLength(): number | undefined { + return this._lineWarningLength; } - set warningLength(warningLength: number) { - this._proxy.$setWarningLength(this._sourceControlHandle, warningLength); - this._warningLength = warningLength; + set lineWarningLength(lineWarningLength: number) { + this._proxy.$setLineWarningLength(this._sourceControlHandle, lineWarningLength); + this._lineWarningLength = lineWarningLength; } constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) { diff --git a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts index d2a18a112ea..bce5b81ee3c 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts @@ -74,5 +74,11 @@ Registry.as(ConfigurationExtensions.Configuration).regis default: 'all', description: localize('diffDecorations', "Controls diff decorations in the editor.") }, + 'scm.inputCounter': { + type: 'string', + enum: ['always', 'warn', 'off'], + default: 'warn', + description: localize('inputCounter', "Controls when to display the input counter.") + } } }); \ No newline at end of file diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 982d059e337..af7f2a6a9b6 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/scmViewlet'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, chain, mapEvent } from 'vs/base/common/event'; +import Event, { Emitter, chain, mapEvent, anyEvent } from 'vs/base/common/event'; import { domEvent, stop } from 'vs/base/browser/event'; import { basename } from 'vs/base/common/paths'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -56,6 +56,7 @@ import { format } from 'vs/base/common/strings'; import { ISpliceable, ISequence, ISplice } from 'vs/base/common/sequence'; import { firstIndex } from 'vs/base/common/arrays'; import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; // TODO@Joao // Need to subclass MenuItemActionItem in order to respect @@ -695,7 +696,8 @@ export class RepositoryPanel extends ViewletPanel { @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IEditorGroupService protected editorGroupService: IEditorGroupService, @IContextKeyService protected contextKeyService: IContextKeyService, - @IInstantiationService protected instantiationService: IInstantiationService + @IInstantiationService protected instantiationService: IInstantiationService, + @IConfigurationService protected configurationService: IConfigurationService ) { super(repository.provider.label, {}, keybindingService, contextMenuService); this.menus = instantiationService.createInstance(SCMMenus, repository.provider); @@ -754,23 +756,46 @@ export class RepositoryPanel extends ViewletPanel { }; const validation = (text: string): IMessage => { - const warningLength = this.repository.input.warningLength; - if (warningLength === undefined) { + const setting = this.configurationService.getValue<'always' | 'warn' | 'off'>('scm.inputCounter'); + + if (setting === 'off') { + return null; + } + + let position = this.inputBox.inputElement.selectionStart; + let start = 0, end; + let match: RegExpExecArray; + const regex = /\r?\n/g; + + while ((match = regex.exec(text)) && position > match.index) { + start = match.index + match[0].length; + } + + end = match ? match.index : text.length; + + const line = text.substring(start, end); + + const lineWarningLength = this.repository.input.lineWarningLength; + + if (lineWarningLength === undefined) { return { - content: localize('commitMessageInfo', "{0} characters", text.length), + content: localize('commitMessageInfo', "{0} characters in current line", text.length), type: MessageType.INFO }; } - const charactersLeft = warningLength - text.length; - if (charactersLeft > 0) { + if (line.length <= lineWarningLength) { + if (setting !== 'always') { + return null; + } + return { - content: localize('commitMessageCountdown', "{0} characters left", text.length), + content: localize('commitMessageCountdown', "{0} characters left in current line", lineWarningLength - line.length), type: MessageType.INFO }; } else { return { - content: localize('commitMessageWarning', "{0} characters over", text.length), + content: localize('commitMessageWarning', "{0} characters over {1} in current line", line.length - lineWarningLength, lineWarningLength), type: MessageType.WARNING }; } @@ -783,6 +808,10 @@ export class RepositoryPanel extends ViewletPanel { this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService)); this.disposables.push(this.inputBox); + const onKeyUp = domEvent(this.inputBox.inputElement, 'keyup'); + const onMouseUp = domEvent(this.inputBox.inputElement, 'mouseup'); + anyEvent(onKeyUp, onMouseUp)(() => this.inputBox.validate(), null, this.disposables); + this.inputBox.value = this.repository.input.value; this.inputBox.onDidChange(value => this.repository.input.value = value, null, this.disposables); this.repository.input.onDidChange(value => this.inputBox.value = value, null, this.disposables); diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index b10ab4dc7cc..78014460542 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -75,7 +75,7 @@ export interface ISCMInput { placeholder: string; readonly onDidChangePlaceholder: Event; - warningLength: number | undefined; + lineWarningLength: number | undefined; } export interface ISCMRepository extends IDisposable { diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index a16e88a7436..ad66331ddc1 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -40,15 +40,7 @@ class SCMInput implements ISCMInput { private _onDidChangePlaceholder = new Emitter(); get onDidChangePlaceholder(): Event { return this._onDidChangePlaceholder.event; } - private _warningLength: number | undefined; - - get warningLength(): number | undefined { - return this._warningLength; - } - - set warningLength(warningLength: number) { - this._warningLength = warningLength; - } + public lineWarningLength: number | undefined = undefined; } class SCMRepository implements ISCMRepository { From 06c9f76202efd73b4b80f415362719dbc5d44eb2 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Tue, 12 Dec 2017 17:57:42 +0100 Subject: [PATCH 08/32] node-debug@1.20.0 --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 587e8ab262a..a68a796a764 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -45,7 +45,7 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.19.7' }, + { name: 'ms-vscode.node-debug', version: '1.20.0' }, { name: 'ms-vscode.node-debug2', version: '1.19.3' } ]; From b0f3ee17066e253860a5a62d98d61a8b5db7cb34 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 12 Dec 2017 18:15:12 +0100 Subject: [PATCH 09/32] Simplify OverviewRuler (fixes #38418) --- .../viewParts/overviewRuler/overviewRuler.ts | 104 ++++-------------- .../editor/browser/widget/diffEditorWidget.ts | 18 +-- .../editor/common/view/overviewZoneManager.ts | 87 ++++----------- 3 files changed, 53 insertions(+), 156 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index ea5e1ba7cfb..1b450611c58 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -11,33 +11,22 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions'; import { OverviewRulerZone, OverviewZoneManager, ColorZone } from 'vs/editor/common/view/overviewZoneManager'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; -import { Color } from 'vs/base/common/color'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { private _context: ViewContext; - private _canvasLeftOffset: number; private _domNode: FastDomNode; - private _lanesCount: number; private _zoneManager: OverviewZoneManager; - private _background: Color; constructor(context: ViewContext, cssClassName: string) { super(); this._context = context; - this._canvasLeftOffset = 0; - this._domNode = createFastDomNode(document.createElement('canvas')); this._domNode.setClassName(cssClassName); this._domNode.setPosition('absolute'); this._domNode.setLayerHinting(true); - this._lanesCount = 3; - - this._background = null; - this._zoneManager = new OverviewZoneManager((lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber)); this._zoneManager.setDOMWidth(0); this._zoneManager.setDOMHeight(0); @@ -60,7 +49,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { if (e.lineHeight) { this._zoneManager.setLineHeight(this._context.configuration.editor.lineHeight); - this.render(true); + this._render(); } if (e.pixelRatio) { @@ -69,23 +58,24 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._domNode.setHeight(this._zoneManager.getDOMHeight()); this._domNode.domNode.width = this._zoneManager.getCanvasWidth(); this._domNode.domNode.height = this._zoneManager.getCanvasHeight(); - this.render(true); + this._render(); } return true; } - public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { + this._render(); return true; } - public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { - this._zoneManager.setOuterHeight(e.scrollHeight); - this.render(true); - return super.onScrollChanged(e) || e.scrollHeightChanged; + if (e.scrollHeightChanged) { + this._zoneManager.setOuterHeight(e.scrollHeight); + this._render(); + } + return true; } - public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean { + this._render(); return true; } @@ -109,16 +99,16 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._domNode.domNode.width = this._zoneManager.getCanvasWidth(); this._domNode.domNode.height = this._zoneManager.getCanvasHeight(); - this.render(true); + this._render(); } } public setZones(zones: OverviewRulerZone[]): void { this._zoneManager.setZones(zones); - this.render(false); + this._render(); } - public render(forceRender: boolean): boolean { + private _render(): boolean { if (this._zoneManager.getOuterHeight() === 0) { return false; } @@ -130,79 +120,29 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { let id2Color = this._zoneManager.getId2Color(); let ctx = this._domNode.domNode.getContext('2d'); - if (this._background === null) { - ctx.clearRect(0, 0, width, height); - } else { - ctx.fillStyle = Color.Format.CSS.formatHex(this._background); - ctx.fillRect(0, 0, width, height); - } - + ctx.clearRect(0, 0, width, height); if (colorZones.length > 0) { - let remainingWidth = width - this._canvasLeftOffset; - - if (this._lanesCount >= 3) { - this._renderThreeLanes(ctx, colorZones, id2Color, remainingWidth); - } else if (this._lanesCount === 2) { - this._renderTwoLanes(ctx, colorZones, id2Color, remainingWidth); - } else if (this._lanesCount === 1) { - this._renderOneLane(ctx, colorZones, id2Color, remainingWidth); - } + this._renderOneLane(ctx, colorZones, id2Color, width); } return true; } - - private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center | OverviewRulerLane.Right, this._canvasLeftOffset, w); - - } - - private _renderTwoLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - let leftWidth = Math.floor(w / 2); - let rightWidth = w - leftWidth; - let leftOffset = this._canvasLeftOffset; - let rightOffset = this._canvasLeftOffset + leftWidth; - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center, leftOffset, leftWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth); - } - - private _renderThreeLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - let leftWidth = Math.floor(w / 3); - let rightWidth = Math.floor(w / 3); - let centerWidth = w - leftWidth - rightWidth; - let leftOffset = this._canvasLeftOffset; - let centerOffset = this._canvasLeftOffset + leftWidth; - let rightOffset = this._canvasLeftOffset + leftWidth + centerWidth; - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left, leftOffset, leftWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Center, centerOffset, centerWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth); - } - - private _renderVerticalPatch(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], laneMask: number, xpos: number, width: number): void { + private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], width: number): void { let currentColorId = 0; let currentFrom = 0; let currentTo = 0; for (let i = 0, len = colorZones.length; i < len; i++) { - let zone = colorZones[i]; + const zone = colorZones[i]; - if (!(zone.position & laneMask)) { - continue; - } - - let zoneColorId = zone.colorId; - let zoneFrom = zone.from; - let zoneTo = zone.to; + const zoneColorId = zone.colorId; + const zoneFrom = zone.from; + const zoneTo = zone.to; if (zoneColorId !== currentColorId) { - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); currentColorId = zoneColorId; ctx.fillStyle = id2Color[currentColorId]; @@ -212,14 +152,14 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { if (currentTo >= zoneFrom) { currentTo = Math.max(currentTo, zoneTo); } else { - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); currentFrom = zoneFrom; currentTo = zoneTo; } } } - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); } } diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 2b2a0ab662d..23eaa557d14 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1594,6 +1594,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd } _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._removeColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1614,12 +1615,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, DECORATIONS.charDeleteWholeLine)); } - let color = this._removeColor.toString(); - result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - color + overviewZoneColor )); if (lineChange.charChanges) { @@ -1655,6 +1654,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd } _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._insertColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1675,11 +1675,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); } - let color = this._insertColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - color + overviewZoneColor )); if (lineChange.charChanges) { @@ -1775,6 +1774,8 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._removeColor.toString(); + let result: IEditorDiffDecorations = { decorations: [], overviewZones: [] @@ -1790,11 +1791,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor options: DECORATIONS.lineDeleteMargin }); - let color = this._removeColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - color + overviewZoneColor )); } } @@ -1803,6 +1803,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._insertColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1821,11 +1822,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); - let color = this._insertColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - color + overviewZoneColor )); if (lineChange.charChanges) { diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index 6d200c3c7f5..92759f72bbe 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -4,9 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; -import { ThemeType } from 'vs/platform/theme/common/themeService'; - const enum Constants { MINIMUM_HEIGHT = 4 } @@ -14,16 +11,24 @@ const enum Constants { export class ColorZone { _colorZoneBrand: void; - from: number; - to: number; - colorId: number; - position: OverviewRulerLane; + public readonly from: number; + public readonly to: number; + public readonly colorId: number; constructor(from: number, to: number, colorId: number) { this.from = from | 0; this.to = to | 0; this.colorId = colorId | 0; - this.position = OverviewRulerLane.Full; + } + + public static compare(a: ColorZone, b: ColorZone): number { + if (a.colorId === b.colorId) { + if (a.from === b.from) { + return a.to - b.to; + } + return a.from - b.from; + } + return a.colorId - b.colorId; } } @@ -50,21 +55,14 @@ export class OverviewRulerZone { this._colorZone = null; } - public getColor(themeType: ThemeType): string { - return this.color; - } - - public compareTo(other: OverviewRulerZone): number { - if (this.startLineNumber === other.startLineNumber) { - if (this.endLineNumber === other.endLineNumber) { - if (this.color === other.color) { - return 0; - } - return this.color < other.color ? -1 : 1; + public static compare(a: OverviewRulerZone, b: OverviewRulerZone): number { + if (a.color === b.color) { + if (a.startLineNumber === b.startLineNumber) { + return a.endLineNumber - b.endLineNumber; } - return this.endLineNumber - other.endLineNumber; + return a.startLineNumber - b.startLineNumber; } - return this.startLineNumber - other.startLineNumber; + return a.color < b.color ? -1 : 1; } public setColorZone(colorZone: ColorZone): void { @@ -111,39 +109,8 @@ export class OverviewZoneManager { } public setZones(newZones: OverviewRulerZone[]): void { - newZones.sort((a, b) => a.compareTo(b)); - - let oldZones = this._zones; - let oldIndex = 0; - let oldLength = this._zones.length; - let newIndex = 0; - let newLength = newZones.length; - - let result: OverviewRulerZone[] = []; - while (newIndex < newLength) { - let newZone = newZones[newIndex]; - - if (oldIndex >= oldLength) { - result.push(newZone); - newIndex++; - } else { - let oldZone = oldZones[oldIndex]; - let cmp = oldZone.compareTo(newZone); - if (cmp < 0) { - oldIndex++; - } else if (cmp > 0) { - result.push(newZone); - newIndex++; - } else { - // cmp === 0 - result.push(oldZone); - oldIndex++; - newIndex++; - } - } - } - - this._zones = result; + this._zones = newZones; + this._zones.sort(OverviewRulerZone.compare); } public setLineHeight(lineHeight: number): boolean { @@ -258,17 +225,7 @@ export class OverviewZoneManager { this._colorZonesInvalid = false; - let sortFunc = (a: ColorZone, b: ColorZone) => { - if (a.colorId === b.colorId) { - if (a.from === b.from) { - return a.to - b.to; - } - return a.from - b.from; - } - return a.colorId - b.colorId; - }; - - allColorZones.sort(sortFunc); + allColorZones.sort(ColorZone.compare); return allColorZones; } } From f472c7095970a8d25dd8e5a32ab03f6fc9732167 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Tue, 12 Dec 2017 18:24:50 +0100 Subject: [PATCH 10/32] update node-debug package-lock --- .../ms-vscode.node-debug/package-lock.json | 96 ++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/extensions/ms-vscode.node-debug/package-lock.json b/extensions/ms-vscode.node-debug/package-lock.json index 82260da1aa1..526e856f483 100644 --- a/extensions/ms-vscode.node-debug/package-lock.json +++ b/extensions/ms-vscode.node-debug/package-lock.json @@ -1,6 +1,6 @@ { "name": "node-debug", - "version": "1.19.2", + "version": "1.19.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -42,21 +42,21 @@ } }, "@types/mocha": { - "version": "2.2.42", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.42.tgz", - "integrity": "sha512-b6gVDoxEbAQGwbV7gSzeFw/hy3/eEAokztktdzl4bHvGgb9K5zW4mVQDlVYch2w31m8t/J7L2iqhQvz3r5edCQ==", + "version": "2.2.44", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", + "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==", "dev": true }, "@types/node": { - "version": "6.0.52", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.52.tgz", - "integrity": "sha1-GsOpm0IyD55GNILyWvTCNZRzqqY=", + "version": "7.0.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.43.tgz", + "integrity": "sha512-7scYwwfHNppXvH/9JzakbVxk0o0QUILVk1Lv64GRaxwPuGpnF1QBiwdvhDpLcymb8BpomQL3KYoWKq3wUdDMhQ==", "dev": true }, "@types/source-map": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.1.tgz", - "integrity": "sha512-/GVAjL1Y8puvZab63n8tsuBiYwZt1bApMdx58/msQ9ID5T05ov+wm/ZV1DvYC/DKKEygpTJViqQvkh5Rhrl4CA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.2.tgz", + "integrity": "sha512-++w4WmMbk3dS3UeHGzAG+xJOSz5Xqtjys/TBkqG3qp3SeWE7Wwezqe5eB7B51cxUyh4PW7bwVotpsLdBK0D8cw==", "dev": true }, "abbrev": { @@ -4755,9 +4755,9 @@ } }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.5.0.tgz", + "integrity": "sha512-v/jMDoK/qKptnTuC3YUNbIj8uUYvTCIHzVu9BHldKSWja48wusAtfjlcBlqnFrqClu3yf69ScDxBPrIyFnF51g==", "dev": true }, "mime-db": { @@ -5149,13 +5149,30 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", + "dev": true, + "requires": { + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, "parse5": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "@types/node": "6.0.52" + "@types/node": "7.0.43" } }, "path-dirname": { @@ -6671,9 +6688,9 @@ } }, "vsce": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.32.0.tgz", - "integrity": "sha1-EN+pIyGCwg6r5r8xJdMzpLIG/j0=", + "version": "1.33.2", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.33.2.tgz", + "integrity": "sha1-NkX2mq+YTiL3TqSdNfON0Y1m/18=", "dev": true, "requires": { "cheerio": "1.0.0-rc.2", @@ -6682,9 +6699,10 @@ "glob": "7.1.2", "lodash": "4.17.4", "markdown-it": "8.4.0", - "mime": "1.4.1", + "mime": "1.5.0", "minimatch": "3.0.4", "osenv": "0.1.4", + "parse-semver": "1.1.1", "read": "1.0.7", "semver": "5.4.1", "tmp": "0.0.29", @@ -6709,9 +6727,9 @@ } }, "vscode": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.6.tgz", - "integrity": "sha1-Ru0a+iwbnWifY5TI8WvR1xkPdfs=", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.8.tgz", + "integrity": "sha512-kT6sIA1AEKR5M+us2fXk5dxwV9SR/IEdLHNmVW4/dl1wNBHoEvgIo1qMQwHNxPVTQmw70KTGZ9UVeVb8FbpNFA==", "dev": true, "requires": { "glob": "7.1.2", @@ -6739,34 +6757,26 @@ } }, "vscode-debugadapter": { - "version": "1.25.0-pre.0", - "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0-pre.0.tgz", - "integrity": "sha1-0pDsVH5h5Pvss2P/9ojSAyMZQmQ=", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0.tgz", + "integrity": "sha512-tsOtNNKKTbnQanARdkFfUxI8qKVKba+QHOKWC1reDDeeyvzoNKkLMGkL/xsiKn5vQDeaP3zFBcLY8Ysak9GrvQ==", "requires": { - "vscode-debugprotocol": "1.25.0-pre.0" - }, - "dependencies": { - "vscode-debugprotocol": { - "version": "1.25.0-pre.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0-pre.0.tgz", - "integrity": "sha1-rYPnvZWxmseV31D6Di/pA0YqcrY=" - } + "vscode-debugprotocol": "1.25.0" } }, "vscode-debugadapter-testsupport": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.24.0.tgz", - "integrity": "sha1-rDZ1scU/wW+1JMvSt+znEhtiXng=", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.25.0.tgz", + "integrity": "sha512-6E2N7CoH7B0KEDvI9mFVFt4H+dRFDhtj3PmLVjNojfZ1VZZS2yfhE0XO0E5Axdhef3zTpUU6WZoeOOMVFGZGIg==", "dev": true, "requires": { - "vscode-debugprotocol": "1.24.0" + "vscode-debugprotocol": "1.25.0" } }, "vscode-debugprotocol": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz", - "integrity": "sha1-28EOjX2VsQJyehmvPw/O9+JSsI4=", - "dev": true + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz", + "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" }, "vscode-nls": { "version": "2.0.2", @@ -6774,9 +6784,9 @@ "integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=" }, "vscode-nls-dev": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.5.tgz", - "integrity": "sha1-GfqjsYp/MCIBA5pMlnu9IvoShE0=", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.6.tgz", + "integrity": "sha512-1IylC/ekENYqz1vEItfrzrMXS8LW9aZQnNTU6BfdwT0Jddzed+l+nvU8amgVKFFmC1/GoiMFk5wtC20zWBbEbw==", "dev": true, "requires": { "clone": "1.0.3", From 14a1996a228b25ada19f7f0f9e5cc419cba1da3e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 12 Dec 2017 18:29:00 +0100 Subject: [PATCH 11/32] load sudo-prompt async --- .../services/files/node/fileService.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index c1551e21910..29546e8fb3d 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -10,7 +10,6 @@ import fs = require('fs'); import os = require('os'); import crypto = require('crypto'); import assert = require('assert'); -import sudoPrompt = require('sudo-prompt'); import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData } from 'vs/platform/files/common/files'; import { MAX_FILE_SIZE } from 'vs/platform/files/node/files'; @@ -598,14 +597,16 @@ export class FileService implements IFileService { return this.updateContent(uri.file(tmpPath), value, writeOptions).then(() => { // 3.) invoke our CLI as super user - return new TPromise((c, e) => { - const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath }; - sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => { - if (error || stderr) { - e(error || stderr); - } else { - c(void 0); - } + return (import('sudo-prompt')).then(sudoPrompt => { + return new TPromise((c, e) => { + const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath }; + sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => { + if (error || stderr) { + e(error || stderr); + } else { + c(void 0); + } + }); }); }).then(() => { From 9eced630d270deae80b377ce743200a5ed558f90 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Dec 2017 10:01:13 -0800 Subject: [PATCH 12/32] Remove trailing closing paren in --status OS version Fixes #40092 --- src/vs/code/electron-main/diagnostics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/diagnostics.ts b/src/vs/code/electron-main/diagnostics.ts index 285e9c504a6..23813aeaec6 100644 --- a/src/vs/code/electron-main/diagnostics.ts +++ b/src/vs/code/electron-main/diagnostics.ts @@ -124,7 +124,7 @@ function formatEnvironment(info: IMainProcessInfo): string { const output: string[] = []; output.push(`Version: ${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`); - output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()})`); + output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()}`); const cpus = os.cpus(); if (cpus && cpus.length > 0) { output.push(`CPUs: ${cpus[0].model} (${cpus.length} x ${cpus[0].speed})`); From f4eca163a0b1939c1b15cb7aacbdc52119b6f061 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 11:02:49 -0800 Subject: [PATCH 13/32] Relax vscode-nls deps --- extensions/markdown/package.json | 4 ++-- extensions/markdown/yarn.lock | 4 ++-- extensions/typescript/package.json | 4 ++-- extensions/typescript/yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index f26564acd10..038c3f1b5e3 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -311,8 +311,8 @@ "highlight.js": "9.5.0", "markdown-it": "^8.4.0", "markdown-it-named-headers": "0.0.4", - "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "2.0.2" + "vscode-extension-telemetry": "^0.0.8", + "vscode-nls": "^2.0.2" }, "devDependencies": { "@types/highlight.js": "9.1.10", diff --git a/extensions/markdown/yarn.lock b/extensions/markdown/yarn.lock index 2b58fcb5d2f..4baed92f526 100644 --- a/extensions/markdown/yarn.lock +++ b/extensions/markdown/yarn.lock @@ -155,14 +155,14 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -vscode-extension-telemetry@0.0.8: +vscode-extension-telemetry@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0" dependencies: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@2.0.2: +vscode-nls@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index 1997b63f7f7..780ff87b24b 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -13,8 +13,8 @@ }, "dependencies": { "semver": "4.3.6", - "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "2.0.1" + "vscode-extension-telemetry": "^0.0.8", + "vscode-nls": "^2.0.2" }, "devDependencies": { "@types/node": "8.0.33", diff --git a/extensions/typescript/yarn.lock b/extensions/typescript/yarn.lock index 7f42682066e..eb4fd8e25fd 100644 --- a/extensions/typescript/yarn.lock +++ b/extensions/typescript/yarn.lock @@ -18,16 +18,16 @@ semver@4.3.6: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" -vscode-extension-telemetry@0.0.8: +vscode-extension-telemetry@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0" dependencies: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.1.tgz#7853866e33f9c50ca415e51b9640d081800e36c6" +vscode-nls@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" winreg@1.2.3: version "1.2.3" From 640cd6624e4bb8c4e87e3f768442f71e147fe44c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 11:07:10 -0800 Subject: [PATCH 14/32] Update request-light in JS extension #40101 --- extensions/javascript/package.json | 2 +- extensions/javascript/yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index 15da42cf0a9..e965afaf1a6 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -12,7 +12,7 @@ "main": "./out/javascriptMain", "dependencies": { "jsonc-parser": "^0.3.1", - "request-light": "^0.2.0", + "request-light": "^0.2.1", "vscode-nls": "^2.0.2" }, "scripts": { diff --git a/extensions/javascript/yarn.lock b/extensions/javascript/yarn.lock index 889a7bad9ce..8edc77e4984 100644 --- a/extensions/javascript/yarn.lock +++ b/extensions/javascript/yarn.lock @@ -46,9 +46,9 @@ ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -request-light@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.0.tgz#922497791c2e68528124dfb82354cf37e4bb2cfc" +request-light@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.1.tgz#986f5a82893e9d1ca6a896ebe6f46c51c6b4557f" dependencies: http-proxy-agent "^0.2.6" https-proxy-agent "^0.3.5" From b1d931fef1d5c90efd458cec1674a8efb6079605 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Tue, 12 Dec 2017 11:07:28 -0800 Subject: [PATCH 15/32] Update lang server in emmet to the same version as others Fixes #40104 --- extensions/emmet/package.json | 2 +- extensions/emmet/yarn.lock | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 84196a8b658..498080ea9f4 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -318,7 +318,7 @@ "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", "@emmetio/math-expression": "^0.1.1", "vscode-emmet-helper": "^1.1.19", - "vscode-languageserver-types": "^3.0.3", + "vscode-languageserver-types": "^3.5.0", "image-size": "^0.5.2", "vscode-nls": "2.0.2" } diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 8d8874a062d..697ec7fb017 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -2059,6 +2059,10 @@ vscode-languageserver-types@^3.0.3: version "3.3.0" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.3.0.tgz#8964dc7c2247536fbefd2d6836bf3febac80dd00" +vscode-languageserver-types@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374" + vscode-nls@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" From 43db454aa5b972401e715d03ae1a35e0c3df7170 Mon Sep 17 00:00:00 2001 From: Ramya Rao Date: Tue, 12 Dec 2017 11:14:59 -0800 Subject: [PATCH 16/32] Run configurationResolver on terminal env vars (#40059) * Run configurationResolver on terminal env vars * Run configurationResolver on terminal env vars from api * Refactor per review comment * Resolve variables in their own function --- .../electron-browser/terminalInstance.ts | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f5886a2d038..5824aa00c2e 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -35,6 +35,8 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; import pkg from 'vs/platform/node/package'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -123,7 +125,9 @@ export class TerminalInstance implements ITerminalInstance { @IInstantiationService private _instantiationService: IInstantiationService, @IClipboardService private _clipboardService: IClipboardService, @IHistoryService private _historyService: IHistoryService, - @IThemeService private _themeService: IThemeService + @IThemeService private _themeService: IThemeService, + @IConfigurationResolverService private _configurationResolverService: IConfigurationResolverService, + @IWorkspaceContextService private _workspaceContextService: IWorkspaceContextService ) { this._instanceDisposables = []; this._processDisposables = []; @@ -585,16 +589,24 @@ export class TerminalInstance implements ITerminalInstance { if (!this._shellLaunchConfig.executable) { this._configHelper.mergeDefaultShellPathAndArgs(this._shellLaunchConfig); } - this._initialCwd = this._getCwd(this._shellLaunchConfig, this._historyService.getLastActiveWorkspaceRoot('file')); + + const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file'); + this._initialCwd = this._getCwd(this._shellLaunchConfig, lastActiveWorkspaceRootUri); + + // Resolve env vars from config and shell + const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); + const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); + const envFromConfig = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot); + const envFromShell = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._shellLaunchConfig.env }, lastActiveWorkspaceRoot); + this._shellLaunchConfig.env = envFromShell; // Merge process env with the env from config - const envFromConfig = { ...process.env }; - const envSettingKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); - TerminalInstance.mergeEnvironments(envFromConfig, this._configHelper.config.env[envSettingKey]); + const parentEnv = { ...process.env }; + TerminalInstance.mergeEnvironments(parentEnv, envFromConfig); // Continue env initialization, merging in the env from the launch // config and adding keys that are needed to create the process - const env = TerminalInstance.createTerminalEnv(envFromConfig, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows); + const env = TerminalInstance.createTerminalEnv(parentEnv, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows); this._process = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], { env, cwd: Uri.parse(path.dirname(require.toUrl('../node/terminalProcess'))).fsPath @@ -636,6 +648,16 @@ export class TerminalInstance implements ITerminalInstance { }, LAUNCHING_DURATION); } + // TODO: Should be protected + private static resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: IStringDictionary, lastActiveWorkspaceRoot: IWorkspaceFolder): IStringDictionary { + Object.keys(env).forEach((key) => { + if (typeof env[key] === 'string') { + env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, env[key]); + } + }); + return env; + } + private _sendPtyDataToXterm(message: { type: string, content: string }): void { if (message.type === 'data') { if (this._widgetManager) { From 8b4e8233e7ab28597d6524ca946d9474b29aaac4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Dec 2017 13:33:47 -0800 Subject: [PATCH 17/32] Remove log --- .../parts/terminal/electron-browser/terminalInstance.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index b2345bb2065..2bf830a0f1b 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -254,7 +254,6 @@ export class TerminalInstance implements ITerminalInstance { */ protected async _createXterm(): TPromise { if (!Terminal) { - console.log('load xterm now'); Terminal = (await import('xterm')).Terminal; // Enable search functionality in xterm.js instance Terminal.loadAddon('search'); From 4199874acb1e358e11073788cbee13bf970ba566 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Tue, 12 Dec 2017 14:23:44 -0800 Subject: [PATCH 18/32] Skip parsing docs when emmet suggestions are disabled --- extensions/emmet/src/defaultCompletionProvider.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index 7d331f575b7..ad611574c05 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -23,6 +23,12 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi const isSyntaxMapped = mappedLanguages[document.languageId] ? true : false; let syntax = getEmmetMode((isSyntaxMapped ? mappedLanguages[document.languageId] : document.languageId), excludedLanguages); + if (!syntax + || emmetConfig['showExpandedAbbreviation'] === 'never' + || ((isSyntaxMapped || syntax === 'jsx') && emmetConfig['showExpandedAbbreviation'] !== 'always')) { + return; + } + const helper = getEmmetHelper(); const extractAbbreviationResults = helper.extractAbbreviation(document, position); if (!extractAbbreviationResults) { @@ -46,12 +52,6 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi } } - if (!syntax - || ((isSyntaxMapped || syntax === 'jsx') - && emmetConfig['showExpandedAbbreviation'] !== 'always')) { - return; - } - let noiseCheckPromise: Thenable = Promise.resolve(); // Fix for https://github.com/Microsoft/vscode/issues/32647 From b44e8b4607185e629844f2b7a3fc6c0e4b4df1f6 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 12 Dec 2017 14:51:02 -0800 Subject: [PATCH 19/32] Rename PUBLIC_GITHUB_TOKEN to GITHUB_TOKEN for use --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 12d94a22d1b..1f28f9d55cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ addons: - libsecret-1-dev before_install: + - export GITHUB_TOKEN=$PUBLIC_GITHUB_TOKEN - git submodule update --init --recursive - git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm - source ./.nvm/nvm.sh From 87c1b9b9528f560238fa44293a560d3dc3780da6 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Tue, 12 Dec 2017 15:41:42 -0800 Subject: [PATCH 20/32] reset focus context key when the webview is disposed (#40130) --- src/vs/workbench/parts/html/browser/webview.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/html/browser/webview.ts index 8589995213b..2df1213dadf 100644 --- a/src/vs/workbench/parts/html/browser/webview.ts +++ b/src/vs/workbench/parts/html/browser/webview.ts @@ -196,6 +196,10 @@ export default class Webview { this._onDidClickLink.dispose(); this._disposables = dispose(this._disposables); + if (this._contextKey) { + this._contextKey.reset(); + } + if (this._webview.parentElement) { this._webview.parentElement.removeChild(this._webview); const findWidgetDomNode = this._webviewFindWidget.getDomNode(); From 90fc6b1739022ef913e3012dccb2d97f69695ad3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 15:50:03 -0800 Subject: [PATCH 21/32] Update javascript jsonc Fixes #40098 --- extensions/javascript/package.json | 2 +- extensions/javascript/yarn.lock | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index e965afaf1a6..42e28260ce3 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -11,7 +11,7 @@ ], "main": "./out/javascriptMain", "dependencies": { - "jsonc-parser": "^0.3.1", + "jsonc-parser": "^1.0.0", "request-light": "^0.2.1", "vscode-nls": "^2.0.2" }, diff --git a/extensions/javascript/yarn.lock b/extensions/javascript/yarn.lock index 8edc77e4984..03e618404f4 100644 --- a/extensions/javascript/yarn.lock +++ b/extensions/javascript/yarn.lock @@ -36,11 +36,9 @@ https-proxy-agent@^0.3.5: debug "2" extend "3" -jsonc-parser@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-0.3.1.tgz#6ebf5c75224368d4b07ef4c26f9434e657472e95" - dependencies: - vscode-nls "^2.0.2" +jsonc-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272" ms@0.7.1: version "0.7.1" From 0b597d0b114b5c0431b1e243377ee090a6da2ff2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 16:09:54 -0800 Subject: [PATCH 22/32] Use SnippetString to construct TS method snippet Fixes #40087 --- .../src/features/completionItemProvider.ts | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index f3800d5cd10..fb8fd36867d 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -399,8 +399,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } private snippetForFunctionCall(detail: CompletionEntryDetails): SnippetString { - const suggestionArgumentNames: string[] = []; - let hasOptionalParemeters = false; + let hasOptionalParameters = false; + let hasAddedParameters = false; + + const snippet = new SnippetString(); + snippet.appendText(detail.name); + snippet.appendText('('); + let parenCount = 0; let i = 0; for (; i < detail.displayParts.length; ++i) { @@ -411,9 +416,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP // Skip optional parameters const nameIsFollowedByOptionalIndicator = next && next.text === '?'; if (!nameIsFollowedByOptionalIndicator) { - suggestionArgumentNames.push(`\${${i + 1}:${part.text}}`); + if (hasAddedParameters) { + snippet.appendText(', '); + } + hasAddedParameters = true; + snippet.appendPlaceholder(part.text); } - hasOptionalParemeters = hasOptionalParemeters || nameIsFollowedByOptionalIndicator; + hasOptionalParameters = hasOptionalParameters || nameIsFollowedByOptionalIndicator; } else if (part.kind === 'punctuation') { if (part.text === '(') { ++parenCount; @@ -421,13 +430,17 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP --parenCount; } else if (part.text === '...' && parenCount === 1) { // Found rest parmeter. Do not fill in any further arguments - hasOptionalParemeters = true; + hasOptionalParameters = true; break; } } } - const codeSnippet = `${detail.name}(${suggestionArgumentNames.join(', ')}${hasOptionalParemeters ? '${' + i + '}' : ''})$0`; - return new SnippetString(codeSnippet); + if (hasOptionalParameters) { + snippet.appendTabstop(); + } + snippet.appendText(')'); + snippet.appendTabstop(0); + return snippet; } private getConfiguration(resource: Uri): Configuration { From 9354489e988e203e2d0c1e0a3e17c0c4cfeea3bf Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 12 Dec 2017 16:57:49 -0800 Subject: [PATCH 23/32] Fix long failing windows search-integration tests due to wrong slashes --- .../search/test/node/textSearch.integrationTest.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts index cdc6ada67da..2a18075876d 100644 --- a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts @@ -306,5 +306,10 @@ suite('Search-integration', function () { }); function makeExpression(...patterns: string[]): glob.IExpression { - return patterns.reduce((glob, cur) => { glob[cur] = true; return glob; }, Object.create(null)); -} \ No newline at end of file + return patterns.reduce((glob, pattern) => { + // glob.ts needs forward slashes + pattern = pattern.replace(/\\/g, '/'); + glob[pattern] = true; + return glob; + }, Object.create(null)); +} From 40c8d176e5351e7d839722ee9f11dfa4c40dc6af Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 12 Dec 2017 16:58:43 -0800 Subject: [PATCH 24/32] test-integration.bat must check the errorlevel after each 'call' --- scripts/test-integration.bat | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index f62b80f5f79..b9a95fa62c9 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -10,14 +10,21 @@ set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5% :: Tests in the extension host call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% :: Integration & performance tests in AMD call .\scripts\test.bat --runGlob **\*.integrationTest.js %* +if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in commonJS (language servers tests...) call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\html\server\out\test\ +if %errorlevel% neq 0 exit /b %errorlevel% rmdir /s /q %VSCODEUSERDATADIR% From 4d42f3d7af74227126af4630e27b67a0f3b7c6d7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 17:03:30 -0800 Subject: [PATCH 25/32] Support extension-less links in the markdown preview Fixes #39945 --- extensions/markdown/media/main.js | 45 ++++++++++++++----- extensions/markdown/src/markdownEngine.ts | 7 ++- .../parts/html/browser/webview-pre.js | 3 +- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/extensions/markdown/media/main.js b/extensions/markdown/media/main.js index ddf21afbbb9..82edb45b983 100644 --- a/extensions/markdown/media/main.js +++ b/extensions/markdown/media/main.js @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - +// @ts-check 'use strict'; (function () { @@ -29,6 +29,13 @@ }; } + function postMessage(command, args) { + window.parent.postMessage({ + command: 'did-click-link', + data: `command:${command}?${encodeURIComponent(JSON.stringify(args))}` + }, 'file://'); + } + /** * Find the html elements that map to a specific target line in the editor. * @@ -196,14 +203,34 @@ const offset = event.pageY; const line = getEditorLineNumberForPageOffset(offset); if (!isNaN(line)) { - const args = [settings.source, line]; - window.parent.postMessage({ - command: "did-click-link", - data: `command:_markdown.didClick?${encodeURIComponent(JSON.stringify(args))}` - }, "file://"); + postMessage('_markdown.didClick', [settings.source, line]); } }); + document.addEventListener('click', event => { + if (!event) { + return; + } + + const baseElement = document.getElementsByTagName('base')[0]; + + /** @type {any} */ + let node = event.target; + while (node) { + if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) { + if (node.href.startsWith('file://')) { + const [path, frag] = node.href.replace(/^file:\/\//i, '').split('#'); + postMessage('_markdown.openDocumentLink', { path, frag }); + event.preventDefault(); + event.stopPropagation(); + break; + } + break; + } + node = node.parentNode; + } + }, true); + if (settings.scrollEditorWithPreview) { window.addEventListener('scroll', throttle(() => { if (scrollDisabled) { @@ -211,11 +238,7 @@ } else { const line = getEditorLineNumberForPageOffset(window.scrollY); if (!isNaN(line)) { - const args = [settings.source, line]; - window.parent.postMessage({ - command: 'did-click-link', - data: `command:_markdown.revealLine?${encodeURIComponent(JSON.stringify(args))}` - }, 'file://'); + postMessage('_markdown.revealLine', [settings.source, line]); } } }, 50)); diff --git a/extensions/markdown/src/markdownEngine.ts b/extensions/markdown/src/markdownEngine.ts index 4ed96316277..a4be37ed984 100644 --- a/extensions/markdown/src/markdownEngine.ts +++ b/extensions/markdown/src/markdownEngine.ts @@ -137,8 +137,9 @@ export class MarkdownEngine { md.normalizeLink = (link: string) => { try { let uri = vscode.Uri.parse(link); - if (!uri.scheme && uri.path && !uri.fragment) { + if (!uri.scheme && uri.path) { // Assume it must be a file + const fragment = uri.fragment; if (uri.path[0] === '/') { const root = vscode.workspace.getWorkspaceFolder(this.currentDocument); if (root) { @@ -147,6 +148,10 @@ export class MarkdownEngine { } else { uri = vscode.Uri.file(path.join(path.dirname(this.currentDocument.path), uri.path)); } + + if (fragment) { + uri = uri.with({ fragment }); + } return normalizeLink(uri.toString(true)); } } catch (e) { diff --git a/src/vs/workbench/parts/html/browser/webview-pre.js b/src/vs/workbench/parts/html/browser/webview-pre.js index 3cfc357897a..29af803b49c 100644 --- a/src/vs/workbench/parts/html/browser/webview-pre.js +++ b/src/vs/workbench/parts/html/browser/webview-pre.js @@ -46,11 +46,12 @@ if (!event || !event.view || !event.view.document) { return; } + + var baseElement = event.view.document.getElementsByTagName('base')[0]; /** @type {any} */ var node = event.target; while (node) { if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) { - var baseElement = event.view.document.getElementsByTagName('base')[0]; if (node.getAttribute('href') === '#') { event.view.scrollTo(0, 0); } else if (node.hash && (node.getAttribute('href') === node.hash || (baseElement && node.href.indexOf(baseElement.href) >= 0))) { From 1b579ed2c1db27ed1b3b212ab24e8fd43ae68038 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 17:10:55 -0800 Subject: [PATCH 26/32] Use es2016 for JS/TS inferred projects by default Fixes #40094 --- extensions/typescript/src/typescriptServiceClient.ts | 2 +- extensions/typescript/src/utils/tsconfig.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index 89964180240..f4c054772c9 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -478,7 +478,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient private getCompilerOptionsForInferredProjects(configuration: TypeScriptServiceConfiguration): Proto.ExternalProjectCompilerOptions { const compilerOptions: Proto.ExternalProjectCompilerOptions = { module: 'CommonJS' as Proto.ModuleKind, - target: 'ES6' as Proto.ScriptTarget, + target: 'Es2016' as Proto.ScriptTarget, allowSyntheticDefaultImports: true, allowNonTsExtensions: true, allowJs: true, diff --git a/extensions/typescript/src/utils/tsconfig.ts b/extensions/typescript/src/utils/tsconfig.ts index fd65741cf5b..62c41e4a7a1 100644 --- a/extensions/typescript/src/utils/tsconfig.ts +++ b/extensions/typescript/src/utils/tsconfig.ts @@ -16,7 +16,7 @@ function getEmptyConfig( config: TypeScriptServiceConfiguration ) { const compilerOptions = [ - '"target": "ES6"', + '"target": "es2016"', '"module": "commonjs"', '"jsx": "preserve"', ]; From a845443e14fddde5cc290b05a56adeec88223259 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 17:26:14 -0800 Subject: [PATCH 27/32] Clean up inferred project config logic --- .../typescript/src/typescriptServiceClient.ts | 15 ++----- extensions/typescript/src/utils/tsconfig.ts | 40 ++++++++++++------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index f4c054772c9..b5cbdc98d73 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -27,6 +27,7 @@ import { TypeScriptServiceConfiguration, TsServerLogLevel } from './utils/config import { TypeScriptVersionProvider, TypeScriptVersion } from './utils/versionProvider'; import { TypeScriptVersionPicker } from './utils/versionPicker'; import * as fileSchemes from './utils/fileSchemes'; +import { inferredProjectConfig } from './utils/tsconfig'; const localize = nls.loadMessageBundle(); @@ -476,20 +477,12 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient } private getCompilerOptionsForInferredProjects(configuration: TypeScriptServiceConfiguration): Proto.ExternalProjectCompilerOptions { - const compilerOptions: Proto.ExternalProjectCompilerOptions = { - module: 'CommonJS' as Proto.ModuleKind, - target: 'Es2016' as Proto.ScriptTarget, + return { + ...inferredProjectConfig(configuration), + allowJs: true, allowSyntheticDefaultImports: true, allowNonTsExtensions: true, - allowJs: true, - jsx: 'Preserve' as Proto.JsxEmit }; - - if (this.apiVersion.has230Features()) { - compilerOptions.checkJs = configuration.checkJs; - compilerOptions.experimentalDecorators = configuration.experimentalDecorators; - } - return compilerOptions; } private serviceExited(restart: boolean): void { diff --git a/extensions/typescript/src/utils/tsconfig.ts b/extensions/typescript/src/utils/tsconfig.ts index 62c41e4a7a1..93f87894377 100644 --- a/extensions/typescript/src/utils/tsconfig.ts +++ b/extensions/typescript/src/utils/tsconfig.ts @@ -5,27 +5,39 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import * as Proto from '../protocol'; + import { TypeScriptServiceConfiguration } from './configuration'; export function isImplicitProjectConfigFile(configFileName: string) { return configFileName.indexOf('/dev/null/') === 0; } -function getEmptyConfig( - isTypeScriptProject: boolean, +export function inferredProjectConfig( + config: TypeScriptServiceConfiguration +): Proto.ExternalProjectCompilerOptions { + const base: Proto.ExternalProjectCompilerOptions = { + module: 'commonjs' as Proto.ModuleKind, + target: 'es2016' as Proto.ScriptTarget, + jsx: 'preserve' as Proto.JsxEmit + }; + + if (config.checkJs) { + base.checkJs = true; + } + + if (config.experimentalDecorators) { + base.experimentalDecorators = true; + } + + return base; +} + +function getEmptyConfigSnippet( config: TypeScriptServiceConfiguration ) { - const compilerOptions = [ - '"target": "es2016"', - '"module": "commonjs"', - '"jsx": "preserve"', - ]; - if (!isTypeScriptProject && config.checkJs) { - compilerOptions.push('"checkJs": true'); - } - if (!isTypeScriptProject && config.experimentalDecorators) { - compilerOptions.push('"experimentalDecorators": true'); - } + const baseConfig = inferredProjectConfig(config); + const compilerOptions = Object.keys(baseConfig).map(key => `"${key}": ${JSON.stringify(baseConfig[key])}`); return new vscode.SnippetString(`{ "compilerOptions": { ${compilerOptions.join(',\n\t\t')}$0 @@ -51,7 +63,7 @@ export async function openOrCreateConfigFile( const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' })); const editor = await vscode.window.showTextDocument(doc, col); if (editor.document.getText().length === 0) { - await editor.insertSnippet(getEmptyConfig(isTypeScriptProject, config)); + await editor.insertSnippet(getEmptyConfigSnippet(config)); } return editor; } From 8ab94979981d3df7a2fb034d97a84972dff88924 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 17:32:33 -0800 Subject: [PATCH 28/32] Make name clearer --- extensions/typescript/src/utils/tsconfig.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/typescript/src/utils/tsconfig.ts b/extensions/typescript/src/utils/tsconfig.ts index 93f87894377..91293a8cc11 100644 --- a/extensions/typescript/src/utils/tsconfig.ts +++ b/extensions/typescript/src/utils/tsconfig.ts @@ -33,7 +33,7 @@ export function inferredProjectConfig( return base; } -function getEmptyConfigSnippet( +function inferredProjectConfigSnippet( config: TypeScriptServiceConfiguration ) { const baseConfig = inferredProjectConfig(config); @@ -63,7 +63,7 @@ export async function openOrCreateConfigFile( const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' })); const editor = await vscode.window.showTextDocument(doc, col); if (editor.document.getText().length === 0) { - await editor.insertSnippet(getEmptyConfigSnippet(config)); + await editor.insertSnippet(inferredProjectConfigSnippet(config)); } return editor; } From 161c47988f0b1d364c1eff2ad26fa94bd8db603d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 17:52:36 -0800 Subject: [PATCH 29/32] Remove logging of TS Server start error message --- extensions/typescript/src/typescriptServiceClient.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index b5cbdc98d73..e823eaba480 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -331,11 +331,9 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient this.error('Starting TSServer failed with error.', err); window.showErrorMessage(localize('serverCouldNotBeStarted', 'TypeScript language server couldn\'t be started. Error message is: {0}', err.message || err)); /* __GDPR__ - "error" : { - "message": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" } - } + "error" : {} */ - this.logTelemetry('error', { message: err.message }); + this.logTelemetry('error'); this.resetClientVersion(); return; } From 2652b3f9b8b77a9184d8d47f610905758ce32a19 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 18:11:14 -0800 Subject: [PATCH 30/32] Support link with line number in md editor Fixes #40140 --- extensions/markdown/src/commands.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/extensions/markdown/src/commands.ts b/extensions/markdown/src/commands.ts index 0051c2fa0f8..af92114b50a 100644 --- a/extensions/markdown/src/commands.ts +++ b/extensions/markdown/src/commands.ts @@ -264,6 +264,16 @@ export class OpenDocumentLinkCommand implements Command { new vscode.Range(line, 0, line, 0), vscode.TextEditorRevealType.AtTop); } + + const lineNumberFragment = args.fragment.match(/^L(\d+)$/); + if (lineNumberFragment) { + const line = +lineNumberFragment[1] - 1; + if (!isNaN(line)) { + return editor.revealRange( + new vscode.Range(line, 0, line, 0), + vscode.TextEditorRevealType.AtTop); + } + } } }; From 6ccc79823dd30b5e3316f4e04fdcb4d3b546efdf Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Dec 2017 18:12:57 -0800 Subject: [PATCH 31/32] Fix fragment name --- extensions/markdown/media/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/markdown/media/main.js b/extensions/markdown/media/main.js index 82edb45b983..4b5cf807476 100644 --- a/extensions/markdown/media/main.js +++ b/extensions/markdown/media/main.js @@ -219,8 +219,8 @@ while (node) { if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) { if (node.href.startsWith('file://')) { - const [path, frag] = node.href.replace(/^file:\/\//i, '').split('#'); - postMessage('_markdown.openDocumentLink', { path, frag }); + const [path, fragment] = node.href.replace(/^file:\/\//i, '').split('#'); + postMessage('_markdown.openDocumentLink', { path, fragment }); event.preventDefault(); event.stopPropagation(); break; From 76662d7b9361104b4ca5c28d787a819c9dd73967 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 12 Dec 2017 21:01:42 -0800 Subject: [PATCH 32/32] Bump node-debug2 (loc) --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index a68a796a764..98c32784879 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -46,7 +46,7 @@ const nodeModules = ['electron', 'original-fs'] const builtInExtensions = [ { name: 'ms-vscode.node-debug', version: '1.20.0' }, - { name: 'ms-vscode.node-debug2', version: '1.19.3' } + { name: 'ms-vscode.node-debug2', version: '1.19.4' } ]; const excludedExtensions = [