From 98f95641290c5822bb01039335f80aca57a0ae23 Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 22:32:40 -0800 Subject: [PATCH 01/16] Add ARIA widget role values to auto-complete --- src/vs/languages/html/common/htmlTags.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 92307ca8d67..4fa5214f8ff 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -142,7 +142,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { 'aria-dropeffect:dropeffect', 'aria-expanded:u', 'aria-flowto', 'aria-grabbed:u', 'aria-haspopup:b', 'aria-hidden:b', 'aria-invalid:invalid', 'aria-label', 'aria-labelledby', 'aria-level', 'aria-live:live', 'aria-multiline:b', 'aria-multiselectable:b', 'aria-orientation:orientation', 'aria-owns', 'aria-posinset', 'aria-pressed:tristate', 'aria-readonly:b', 'aria-relevant:relevant', 'aria-required:b', 'aria-selected:u', 'aria-setsize', 'aria-sort:sort', 'aria-valuemax', 'aria-valuemin', 'aria-valuenow', 'aria-valuetext', 'accesskey', - 'class', 'contenteditable:b', 'contextmenu', 'dir:d', 'draggable:a', 'dropzone', 'hidden:v', 'id', 'inert:v', 'itemid', 'itemprop', 'itemref', 'itemscope:v', 'itemtype', 'lang', 'role', + 'class', 'contenteditable:b', 'contextmenu', 'dir:d', 'draggable:a', 'dropzone', 'hidden:v', 'id', 'inert:v', 'itemid', 'itemprop', 'itemref', 'itemscope:v', 'itemtype', 'lang', 'role:roles', 'spellcheck:b', 'style', 'tabindex', 'title', 'translate']; var eventHandlers = ['onabort', 'onblur', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'oncontextmenu', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', @@ -167,7 +167,9 @@ export function getHTML5TagProvider(): IHTMLTagProvider { live: ['off', 'polite', 'assertive'], orientation: ['vertical', 'horizontal'], relevant: ['additions', 'removals', 'text', 'all', 'additions text'], - sort: ['ascending', 'descending', 'none', 'other'] + sort: ['ascending', 'descending', 'none', 'other'], + roles: ['alert', 'alertdialog', 'button', 'checkbox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'scrollbar', 'searchbox', 'slider', + 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem'] }; return { From 0861d8237f1cfc5297e100787b3f5a380dc80911 Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 22:37:12 -0800 Subject: [PATCH 02/16] Add the composite widgets aria role values to auto-complete --- src/vs/languages/html/common/htmlTags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 4fa5214f8ff..9156ad7477f 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -169,7 +169,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { relevant: ['additions', 'removals', 'text', 'all', 'additions text'], sort: ['ascending', 'descending', 'none', 'other'], roles: ['alert', 'alertdialog', 'button', 'checkbox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'scrollbar', 'searchbox', 'slider', - 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem'] + 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'] }; return { From c878d1ecb66d93e112c2ca59a435cff80920974f Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 22:43:00 -0800 Subject: [PATCH 03/16] Add ARIA document structure role values to auto-complete --- src/vs/languages/html/common/htmlTags.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 9156ad7477f..461e7ab6d25 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -169,7 +169,9 @@ export function getHTML5TagProvider(): IHTMLTagProvider { relevant: ['additions', 'removals', 'text', 'all', 'additions text'], sort: ['ascending', 'descending', 'none', 'other'], roles: ['alert', 'alertdialog', 'button', 'checkbox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'scrollbar', 'searchbox', 'slider', - 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'] + 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid', + 'application', 'article', 'cell', 'columnheader', 'definition', 'directory', 'document', 'feed', 'figure', 'group', 'heading', 'img', 'list', 'listitem', 'math', 'none', 'note', 'presentation', 'region', 'row', 'rowgroup', + 'rowheader', 'separator', 'table', 'term', 'text', 'toolbar'] }; return { From 29e329434b209102bbf2d466c213b3f5a558a6ee Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 22:45:29 -0800 Subject: [PATCH 04/16] Add ARIA landmark role values to auto-complete --- src/vs/languages/html/common/htmlTags.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 461e7ab6d25..bcfb1a8e40a 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -171,7 +171,8 @@ export function getHTML5TagProvider(): IHTMLTagProvider { roles: ['alert', 'alertdialog', 'button', 'checkbox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'scrollbar', 'searchbox', 'slider', 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid', 'application', 'article', 'cell', 'columnheader', 'definition', 'directory', 'document', 'feed', 'figure', 'group', 'heading', 'img', 'list', 'listitem', 'math', 'none', 'note', 'presentation', 'region', 'row', 'rowgroup', - 'rowheader', 'separator', 'table', 'term', 'text', 'toolbar'] + 'rowheader', 'separator', 'table', 'term', 'text', 'toolbar', + 'banner', 'complementary', 'contentinfo', 'form', 'main', 'navigation', 'region', 'search'] }; return { From 1dcf795bc9e1e02312aab72de03a2b0f1cbdadc0 Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 23:16:43 -0800 Subject: [PATCH 05/16] Add ARIA 1.1 attributes to global attributes list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …including adding undefined value to orientation --- src/vs/languages/html/common/htmlTags.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index bcfb1a8e40a..2011d998328 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -138,12 +138,12 @@ export function getHTML5TagProvider(): IHTMLTagProvider { }; var globalAttributes = [ - 'aria-activedescendant', 'aria-atomic:b', 'aria-autocomplete:autocomplete', 'aria-busy:b', 'aria-checked:tristate', 'aria-controls', 'aria-describedby', 'aria-disabled:b', - 'aria-dropeffect:dropeffect', 'aria-expanded:u', 'aria-flowto', 'aria-grabbed:u', 'aria-haspopup:b', 'aria-hidden:b', 'aria-invalid:invalid', 'aria-label', 'aria-labelledby', - 'aria-level', 'aria-live:live', 'aria-multiline:b', 'aria-multiselectable:b', 'aria-orientation:orientation', 'aria-owns', 'aria-posinset', 'aria-pressed:tristate', 'aria-readonly:b', - 'aria-relevant:relevant', 'aria-required:b', 'aria-selected:u', 'aria-setsize', 'aria-sort:sort', 'aria-valuemax', 'aria-valuemin', 'aria-valuenow', 'aria-valuetext', 'accesskey', - 'class', 'contenteditable:b', 'contextmenu', 'dir:d', 'draggable:a', 'dropzone', 'hidden:v', 'id', 'inert:v', 'itemid', 'itemprop', 'itemref', 'itemscope:v', 'itemtype', 'lang', 'role:roles', - 'spellcheck:b', 'style', 'tabindex', 'title', 'translate']; + 'aria-activedescendant', 'aria-atomic:b', 'aria-autocomplete:autocomplete', 'aria-busy:b', 'aria-checked:tristate', 'aria-colcount', 'aria-colindex', 'aria-colspan', 'aria-controls', 'aria-current:current', 'aria-describedat', + 'aria-describedby', 'aria-disabled:b', 'aria-dropeffect:dropeffect', 'aria-errormessage', 'aria-expanded:u', 'aria-flowto', 'aria-grabbed:u', 'aria-haspopup:b', 'aria-hidden:b', 'aria-invalid:invalid', 'aria-kbdshortcuts', + 'aria-label', 'aria-labelledby', 'aria-level', 'aria-live:live', 'aria-modal:b', 'aria-multiline:b', 'aria-multiselectable:b', 'aria-orientation:orientation', 'aria-owns', 'aria-placeholder', 'aria-posinset', 'aria-pressed:tristate', + 'aria-readonly:b','aria-relevant:relevant', 'aria-required:b', 'aria-roledescription', 'aria-rowcount', 'aria-rowindex', 'aria-rowspan', 'aria-selected:u', 'aria-setsize', 'aria-sort:sort', 'aria-valuemax', 'aria-valuemin', 'aria-valuenow', 'aria-valuetext', + 'accesskey', 'class', 'contenteditable:b', 'contextmenu', 'dir:d', 'draggable:a', 'dropzone', 'hidden:v', 'id', 'inert:v', 'itemid', 'itemprop', 'itemref', 'itemscope:v', 'itemtype', 'lang', 'role:roles', 'spellcheck:b', 'style', 'tabindex', + 'title', 'translate']; var eventHandlers = ['onabort', 'onblur', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'oncontextmenu', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'ondurationchange', 'onemptied', 'onended', 'onerror', 'onfocus', 'onformchange', 'onforminput', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onloadeddata', 'onloadedmetadata', @@ -162,10 +162,11 @@ export function getHTML5TagProvider(): IHTMLTagProvider { xo: ['anonymous', 'use-credentials'], tristate: ['true', 'false', 'mixed', 'undefined'], autocomplete: ['inline', 'list', 'both', 'none'], + current: ['page', 'step', 'location', 'date', 'time', 'true', 'false'], dropeffect: ['copy', 'move', 'link', 'execute', 'popup', 'none'], invalid: ['grammar', 'false', 'spelling', 'true'], live: ['off', 'polite', 'assertive'], - orientation: ['vertical', 'horizontal'], + orientation: ['vertical', 'horizontal', 'undefined'], relevant: ['additions', 'removals', 'text', 'all', 'additions text'], sort: ['ascending', 'descending', 'none', 'other'], roles: ['alert', 'alertdialog', 'button', 'checkbox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'scrollbar', 'searchbox', 'slider', From 2d54b7e0ea86fb9e8c62701c305835b5d118562c Mon Sep 17 00:00:00 2001 From: David Storey Date: Sat, 21 Nov 2015 23:33:25 -0800 Subject: [PATCH 06/16] Add tests for ARIA 1.1 attribute auto-complete --- .../languages/html/test/common/html-worker.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/vs/languages/html/test/common/html-worker.test.ts b/src/vs/languages/html/test/common/html-worker.test.ts index 43b2dde3f52..2866715625f 100644 --- a/src/vs/languages/html/test/common/html-worker.test.ts +++ b/src/vs/languages/html/test/common/html-worker.test.ts @@ -237,29 +237,42 @@ suite('HTML - worker', () => { assertSuggestion(completion, 'aria-autocomplete'); assertSuggestion(completion, 'aria-busy'); assertSuggestion(completion, 'aria-checked'); + assertSuggestion(completion, 'aria-colcount'); + assertSuggestion(completion, 'aria-colindex'); + assertSuggestion(completion, 'aria-colspan'); assertSuggestion(completion, 'aria-controls'); + assertSuggestion(completion, 'aria-current'); + assertSuggestion(completion, 'aria-describedat'); assertSuggestion(completion, 'aria-describedby'); assertSuggestion(completion, 'aria-disabled'); assertSuggestion(completion, 'aria-dropeffect'); + assertSuggestion(completion, 'aria-errormessage'); assertSuggestion(completion, 'aria-expanded'); assertSuggestion(completion, 'aria-flowto'); assertSuggestion(completion, 'aria-grabbed'); assertSuggestion(completion, 'aria-haspopup'); assertSuggestion(completion, 'aria-hidden'); assertSuggestion(completion, 'aria-invalid'); + assertSuggestion(completion, 'aria-kbdshortcuts'); assertSuggestion(completion, 'aria-label'); assertSuggestion(completion, 'aria-labelledby'); assertSuggestion(completion, 'aria-level'); assertSuggestion(completion, 'aria-live'); + assertSuggestion(completion, 'aria-modal'); assertSuggestion(completion, 'aria-multiline'); assertSuggestion(completion, 'aria-multiselectable'); assertSuggestion(completion, 'aria-orientation'); assertSuggestion(completion, 'aria-owns'); + assertSuggestion(completion, 'aria-placeholder'); assertSuggestion(completion, 'aria-posinset'); assertSuggestion(completion, 'aria-pressed'); assertSuggestion(completion, 'aria-readonly'); assertSuggestion(completion, 'aria-relevant'); assertSuggestion(completion, 'aria-required'); + assertSuggestion(completion, 'aria-roledescription'); + assertSuggestion(completion, 'aria-rowcount'); + assertSuggestion(completion, 'aria-rowindex'); + assertSuggestion(completion, 'aria-rowspan'); assertSuggestion(completion, 'aria-selected'); assertSuggestion(completion, 'aria-setsize'); assertSuggestion(completion, 'aria-sort'); From 2b6ba9e3cb5c57170b67623395a008c96bf5ebce Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:18:57 +0100 Subject: [PATCH 07/16] prevent an extension from process.exit() (fixes #411) --- src/vs/workbench/node/pluginHostMain.ts | 10 ++++++++-- src/vs/workbench/node/pluginHostProcess.ts | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index 57e9c39e49f..b8314c2fbe4 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -55,6 +55,12 @@ export interface IInitData { }; } +const nativeExit = process.exit; +process.exit = () => { console.warn('An extension called process.exit() and this was prevented'); }; +export function exit(code?: number) { + nativeExit(code); +} + export function createServices(remoteCom: IPluginsIPC, initData: IInitData, sharedProcessClient: Client): IInstantiationService { // the init data is not demarshalled initData = marshalling.deserialize(initData); @@ -249,7 +255,7 @@ export class PluginHostMain { private gracefulExit(): void { // to give the PH process a chance to flush any outstanding console - // messages to the main process, we delay the process.exit() by some time - setTimeout(() => process.exit(), 500); + // messages to the main process, we delay the exit() by some time + setTimeout(() => exit(), 500); } } \ No newline at end of file diff --git a/src/vs/workbench/node/pluginHostProcess.ts b/src/vs/workbench/node/pluginHostProcess.ts index b998fcf82cc..c62d4267abb 100644 --- a/src/vs/workbench/node/pluginHostProcess.ts +++ b/src/vs/workbench/node/pluginHostProcess.ts @@ -7,7 +7,7 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import { TPromise } from 'vs/base/common/winjs.base'; -import { PluginHostMain, createServices, IInitData } from 'vs/workbench/node/pluginHostMain'; +import { PluginHostMain, createServices, IInitData, exit } from 'vs/workbench/node/pluginHostMain'; import { Client, connect } from 'vs/base/node/service.net'; import { create as createIPC, IPluginsIPC } from 'vs/platform/plugins/common/ipcRemoteCom'; @@ -50,7 +50,7 @@ function connectToRenderer(): TPromise { try { process.kill(msg.parentPid, 0); // throws an exception if the main process doesn't exist anymore. } catch (e) { - process.exit(); + exit(); } }, 5000); From ed9a93cc7272bf29a74d6ff05ef217fa9e0932d9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:28:26 +0100 Subject: [PATCH 08/16] fix message list ordering (fixes #279) --- src/vs/base/browser/ui/messagelist/messageList.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/browser/ui/messagelist/messageList.ts b/src/vs/base/browser/ui/messagelist/messageList.ts index 4dc5aec208c..f4fd2588017 100644 --- a/src/vs/base/browser/ui/messagelist/messageList.ts +++ b/src/vs/base/browser/ui/messagelist/messageList.ts @@ -130,8 +130,8 @@ export class MessageList { // Trigger Auto-Purge of messages to keep list small this.purgeMessages(); - // Store in Memory - this.messages.push({ + // Store in Memory (new messages come first so that they show up on top) + this.messages.unshift({ id: id, text: message, severity: severity, From cfbddb849e205b094295c71247529293279b7ff1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:35:13 +0100 Subject: [PATCH 09/16] improve settings parsing readability --- src/vs/workbench/node/userSettings.ts | 56 ++++++++++++++------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/node/userSettings.ts b/src/vs/workbench/node/userSettings.ts index 83dd90840a2..2c58de5c0aa 100644 --- a/src/vs/workbench/node/userSettings.ts +++ b/src/vs/workbench/node/userSettings.ts @@ -48,22 +48,21 @@ export class UserSettings { const appSettingsPath = contextService.getConfiguration().env.appSettingsPath; fs.readFile(appSettingsPath, (error /* ignore */, fileContents) => { - let root = {}; - let content = fileContents && fileContents.toString(); - if (!content) { - content = '{}'; - } + let root = Object.create(null); + let content = fileContents ? fileContents.toString() : '{}'; + let contents = Object.create(null); try { - let contents = json.parse(content) || {}; - for (let key in contents) { - UserSettings.setNode(root, key, contents[key]); - } - - return c(UserSettings.doGetValue(root, key, fallback)); + contents = json.parse(content); } catch (error) { - return c(UserSettings.doGetValue(root, key, fallback)); // parse error + // ignore parse problem } + + for (let key in contents) { + UserSettings.setNode(root, key, contents[key]); + } + + return c(UserSettings.doGetValue(root, key, fallback)); }); }); } @@ -142,29 +141,32 @@ export class UserSettings { } private doLoadSettingsSync(): { contents: any; parseErrors?: string[]; } { + let root = Object.create(null); + let content = '{}'; try { - let root = {}; - let content = '{}'; - try { - content = fs.readFileSync(this.appSettingsPath).toString(); - } catch (error) { - // ignore - } + content = fs.readFileSync(this.appSettingsPath).toString(); + } catch (error) { + // ignore + } - let contents = json.parse(content) || {}; - for (let key in contents) { - UserSettings.setNode(root, key, contents[key]); - } - return { - contents: root - }; + let contents = Object.create(null); + try { + contents = json.parse(content); } catch (error) { // parse problem return { - contents: {}, + contents: Object.create(null), parseErrors: [this.appSettingsPath] }; } + + for (let key in contents) { + UserSettings.setNode(root, key, contents[key]); + } + + return { + contents: root + }; } private static setNode(root: any, key: string, value: any): any { From 46c0393a24c5ad660f6ca8fcdb7b72f7e14878fe Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:41:14 +0100 Subject: [PATCH 10/16] try workaround for not being able to focus window on win & linux --- src/vs/workbench/electron-browser/window.ts | 6 +++++- src/vs/workbench/electron-main/window.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index a82898ad10f..89755c55e64 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -174,7 +174,11 @@ export class ElectronWindow { public focus(): void { if (!this.win.isFocused()) { - this.win.focus(); + if (platform.isWindows || platform.isLinux) { + this.win.show(); // Windows & Linux sometimes cannot bring the window to the front when it is in the background + } else { + this.win.focus(); + } } } diff --git a/src/vs/workbench/electron-main/window.ts b/src/vs/workbench/electron-main/window.ts index b7d003c2f39..c924a897af2 100644 --- a/src/vs/workbench/electron-main/window.ts +++ b/src/vs/workbench/electron-main/window.ts @@ -215,7 +215,11 @@ export class VSCodeWindow { this._win.restore(); } - this._win.focus(); + if (platform.isWindows || platform.isLinux) { + this._win.show(); // Windows & Linux sometimes cannot bring the window to the front when it is in the background + } else { + this._win.focus(); + } } public get lastFocusTime(): number { From c3094f380d5010a7dd43868a00177a5ff7261124 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:53:08 +0100 Subject: [PATCH 11/16] OutputChannel.hide throws error (fix #377) --- .../api/browser/extHostOutputService.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/api/browser/extHostOutputService.ts b/src/vs/workbench/api/browser/extHostOutputService.ts index 4a64a20caf1..2fed91fe4a1 100644 --- a/src/vs/workbench/api/browser/extHostOutputService.ts +++ b/src/vs/workbench/api/browser/extHostOutputService.ts @@ -5,8 +5,9 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; -import {IOutputService, OUTPUT_MODE_ID} from 'vs/workbench/parts/output/common/output'; +import {IOutputService, OUTPUT_EDITOR_INPUT_ID} from 'vs/workbench/parts/output/common/output'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {Position} from 'vs/platform/editor/common/editor'; import * as TypeConverters from 'vs/workbench/api/common/pluginHostTypeConverters'; @@ -76,35 +77,33 @@ export class ExtHostOutputService { @Remotable.MainContext('MainThreadOutputService') export class MainThreadOutputService { - private _outputService: IOutputService; - private _editorService: IWorkbenchEditorService; - - constructor(@IOutputService outputService: IOutputService, editorService: IWorkbenchEditorService) { - this._outputService = outputService; - this._editorService = editorService; + constructor( + @IOutputService private outputService: IOutputService, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService + ) { } public append(channel: string, value: string): TPromise { - this._outputService.append(channel, value); + this.outputService.append(channel, value); return undefined; } public clear(channel: string): TPromise { - this._outputService.clearOutput(channel); + this.outputService.clearOutput(channel); return undefined; } public reveal(channel: string, position: Position): TPromise { - this._outputService.showOutput(channel, position); + this.outputService.showOutput(channel, position); return undefined; } public close(channel: string): TPromise { - let editors = this._editorService.getVisibleEditors(); + let editors = this.editorService.getVisibleEditors(); for (let editor of editors) { - if (editor.input.getId() === OUTPUT_MODE_ID) { - this._editorService.closeEditor(editor); - return; + if (editor.input.getId() === OUTPUT_EDITOR_INPUT_ID) { + this.editorService.closeEditor(editor).done(null, onUnexpectedError); + return undefined; } } } From 9d1ae7bbe6f871f82bc825bbf324dc0a926df5e2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 10:56:55 +0100 Subject: [PATCH 12/16] trace the stack when process.exit is called from an extension --- src/vs/workbench/node/pluginHostMain.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index b8314c2fbe4..27037d18ed5 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -56,7 +56,10 @@ export interface IInitData { } const nativeExit = process.exit; -process.exit = () => { console.warn('An extension called process.exit() and this was prevented'); }; +process.exit = () => { + const err = new Error('An extension called process.exit() and this was prevented.'); + console.warn((err).stack); +}; export function exit(code?: number) { nativeExit(code); } From 6be95ed398fb62675e6acf71e18d85c518e7ae04 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 11:06:41 +0100 Subject: [PATCH 13/16] less hectic quick open visibility changes --- .../parts/quickopen/quickOpenController.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 8c507269e8e..0b040799230 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -76,6 +76,7 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe private previousActiveHandlerDescriptor: QuickOpenHandlerDescriptor; private actionProvider = new ContributableActionProvider(); private previousValue = ''; + private visibilityChangeTimeoutHandle: number; constructor( private eventService: IEventService, @@ -208,7 +209,7 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe onOk: () => { /* ignore, handle later */ }, onCancel: () => { /* ignore, handle later */ }, onType: (value: string) => { /* ignore, handle later */ }, - onShow: () => this._onShow.fire() + onShow: () => this.emitQuickOpenVisibilityChange(true) }, { inputPlaceHolder: options.placeHolder || '' }, @@ -348,11 +349,11 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe this.pickOpenWidget.refresh(model, value ? { autoFocusFirstEntry: true } : autoFocus); }, onShow: () => { - this._onShow.fire(); // event + this.emitQuickOpenVisibilityChange(true); // event }, onHide: () => { this.restoreFocus(); // focus back to editor or viewlet - this._onHide.fire(); // event + this.emitQuickOpenVisibilityChange(false); // event } }); @@ -378,6 +379,22 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe }); } + private emitQuickOpenVisibilityChange(isVisible: boolean): void { + if (this.visibilityChangeTimeoutHandle) { + window.clearTimeout(this.visibilityChangeTimeoutHandle); + } + + this.visibilityChangeTimeoutHandle = setTimeout(() => { + if (isVisible) { + this._onShow.fire(); + } else { + this._onHide.fire(); + } + + this.visibilityChangeTimeoutHandle = void 0; + }, 100 /* to prevent flashing, we accumulate visibility changes over a timeout of 100ms */); + } + public refresh(input?: string): TPromise { if (!this.quickOpenWidget.isVisible()) { return TPromise.as(null); @@ -421,7 +438,7 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe onType: (value: string) => this.onType(value || ''), onShow: () => { this.inQuickOpenMode.set(true); - this._onShow.fire(); + this.emitQuickOpenVisibilityChange(true); }, onHide: () => { this.inQuickOpenMode.reset(); @@ -432,7 +449,7 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe } this.restoreFocus(); // focus back to editor or viewlet - this._onHide.fire(); + this.emitQuickOpenVisibilityChange(false); } }, { inputPlaceHolder: this.hasHandler(HELP_PREFIX) ? nls.localize('quickOpenInput', "Type '?' to get help on the actions you can take from here") : '' From 7a780d749474d2f05a6d7d2b551fb11007089792 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 11:35:53 +0100 Subject: [PATCH 14/16] dont use lambda in this case --- src/vs/workbench/node/pluginHostMain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index 27037d18ed5..cdd8c531459 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -56,7 +56,7 @@ export interface IInitData { } const nativeExit = process.exit; -process.exit = () => { +process.exit = function() { const err = new Error('An extension called process.exit() and this was prevented.'); console.warn((err).stack); }; From b75d17c3f7bd05c0dc341a930e50d36042fa3632 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 22 Nov 2015 14:23:48 +0100 Subject: [PATCH 15/16] support to release "shift" key in quick open (fixes #265) --- src/vs/base/parts/quickopen/browser/quickOpenWidget.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 119dbefd2d1..7f7e06b6f1c 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -201,6 +201,10 @@ export class QuickOpenWidget implements IModelProvider { let quickNavKeys = this.quickNavigateConfiguration.keybindings; let wasTriggerKeyPressed = keyCode === KeyCode.Enter || quickNavKeys.some((k) => { if (k.hasShift() && keyCode === KeyCode.Shift) { + if (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) { + return false; // this is an optimistic check for the shift key being used to navigate back in quick open + } + return true; } From c7451c15d275fc422004c846ccc77056bb39580f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Sun, 22 Nov 2015 16:38:36 +0100 Subject: [PATCH 16/16] PHP autocompletion: $_GET completes into $$_GET #86 --- extensions/php/src/phpMain.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/php/src/phpMain.ts b/extensions/php/src/phpMain.ts index 9b39e6cb0ca..1367d33d571 100644 --- a/extensions/php/src/phpMain.ts +++ b/extensions/php/src/phpMain.ts @@ -20,4 +20,9 @@ export function activate(context: ExtensionContext): any { let validator = new PHPValidationProvider(); validator.activate(context.subscriptions); + + // need to set in the plugin host as well as the completion provider uses it. + languages.setLanguageConfiguration('php', { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g + }); } \ No newline at end of file